android4.0电源管理详解

在PowerMangerService启动:
class.ServerThread.run(){    @SystemServer.java
    PowerManagerService power = null; //SystemServer内声明PMS实例power
    power = new PowerManagerService();    //创建PMS实例,调用PMS的构造函数
        class.PowerManagerService.PowerManagerService(){
            long token = Binder.clearCallingIdentity(); //PMS.pid,uid改变成PMS自己的
            MY_UID = Process.myUid();    //获得进程用户id
            MY_PID = Process.myPid();    //获得进程id
            Binder.restoreCallingIdentity(token);    //保存重置后的身份到之前身份,即给新PMS换身份
            Power.setLastUserActivityTimeout(7*24*3600*1000);
            mUserState = mPowerState = 0;    //假设电源和用户状态都是on
            Watchdog.getInstance().addMonitor(this);    //添加自己到watchdog
        }
    ServiceManager.addService(Context.POWER_SERVICE, power);
        class.ServiceManager.addService(String name, IBinder service){
            getIServiceManager().addService(name, service);  //serviceManager添加一个service
        }
    power.init(context, lights, ActivityManagerService.self(), battery);    //调用PMS.init,传lights,battery,activity三个服务进去
        class.PowerManagerService.init(Context context, LightsService lights, IActivityManager activity,BatteryService battery){
            mLightsService = lights;    //lights句柄赋给PMS
            mContext = context;
            mActivityService = activity;    //activity句柄赋给PMS
            mBatteryStats = BatteryStatsService.getService();    //获取电池状态服务句柄
            mBatteryService = battery;        //battery句柄赋给PMS

            mLcdLight = lights.getLight(LightsService.LIGHT_ID_BACKLIGHT);        //屏幕亮度
            mButtonLight = lights.getLight(LightsService.LIGHT_ID_BUTTONS);        //按钮亮度
            mKeyboardLight = lights.getLight(LightsService.LIGHT_ID_KEYBOARD);        //键盘亮度
            mAttentionLight = lights.getLight(LightsService.LIGHT_ID_ATTENTION);    //

            nativeInit();    //初始化native层资源 gPowerManagerServiceObj = env->NewGlobalRef(obj);

            updateNativePowerStateLocked();{ //调用native函数,设置native层的两个变量值
                nativeSetPowerState((mPowerState & SCREEN_ON_BIT) != 0,(mPowerState & SCREEN_BRIGHT) == SCREEN_BRIGHT);
            }

            mScreenOffThread = new HandlerThread("PowerManagerService.mScreenOffThread") {
                @Override        //该线程主要处理power键,屏幕变暗
                protected void onLooperPrepared() {
                    mScreenOffHandler = new Handler();
                    synchronized (mScreenOffThread) {
                        mInitComplete = true;
                        mScreenOffThread.notifyAll();
                    }
                }
            };

            mHandlerThread = new HandlerThread("PowerManagerService") {
                @Override        //PMS的重要线程,他的主要工作在initInThread()内完成
                protected void onLooperPrepared() {
                    super.onLooperPrepared();
                    initInThread();
                    PMS.initInThread(){
                        //1,注册一些广播,接受注入启动完毕、电池状态变化等广播
                        //2,读取配置参数。PoMS根据这些参数进行电源管理,这些参数有些是固定的(编译会不能改动),有些可以通过Settings修改
                        //3,PoMS需要对外发出一些通知,例如屏幕关闭/开启。
                    }//endl-initInThread
                }
            };

            nativeInit();
            synchronized (mLocks) {
                updateNativePowerStateLocked();    //最后更新下电源状态
                forceUserActivityLocked();    //点亮屏幕
            }

        } //endl-pms.init

    power.systemReady();
        class.PowerManagerService.systemReady(){
            mSensorManager = new SensorManager(mHandlerThread.getLooper());    //获取sensorManager实例
            mProximitySensor = mSensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY);
            if (mUseSoftwareAutoBrightness) {
                mLightSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_LIGHT);
            }    //初始化两个感应器:sensor和proximitysensor(近物感应:手机打电话距离脸近会关闭屏幕省电)

            if (mUseSoftwareAutoBrightness) {
                // turn the screen on
                setPowerState(SCREEN_BRIGHT);
            } else {
                // turn everything on
                setPowerState(ALL_BRIGHT);
            }

            synchronized (mLocks) {
                enableLightSensorLocked(mUseSoftwareAutoBrightness && mAutoBrightessEnabled);
                try {        //电源状态设置
                    mBatteryStats.noteScreenBrightness(getPreferredBrightness());
                    mBatteryStats.noteScreenOn();
                }
            }
        }//endl-systemReady

    void bootCompleted() {   @PowerManagerService.java
        synchronized (mLocks) {
            mBootCompleted = true;
            userActivity(SystemClock.uptimeMillis(), false, BUTTON_EVENT, true);
            updateWakeLockLocked();
            mLocks.notifyAll();
        }
    }
    在pms的initInThread()函数中创建了一个消息过滤接收器,当系统的服务都在systemReady处理业务完成后,
    系统会广播一次ACTION_BOOT_COMPLETED消息(貌似在ActivityManagerService发出ACTION_BOOT_COMPLETED消息的广播),PMS会处理该广播:
    主要调用userctivity处理用户的BUTTON_EVENT事件,接着调用updateWakeLocked来更新当前WakeLock的状态。

}
启动完成





PowerMangerService工作原理:

PowerManager.java:
class.PowerManager{

    public PowerManager(IPowerManager service, Handler handler){ //PM构造函数,主要是把IPowerManager的变量传进来,PMS继承IPowerManager类,但传的是PMS实例
        mService = service;
        mHandler = handler;
    }

    class.WakeLock{
        WakeLock(int flags, String tag){
            mFlags = flags; //给锁类型赋值flags参数
            mTag = tag;        //tag赋值
            mToken = new Binder();    //创建binder,binder为PM.WakeLock向PMS,native,kernel传递的识别标识
        }

        setReferenceCounted(boolean value) //给this.mRefCounted赋值value,设置this(锁)是否是计数锁

        acquire() //wakelock.acquire(), app通过实现WakeLock实例调用该函数,来跟PMS交互。
            -> acquireLocked();  

        acquire(long timeout)
            -> {acquireLocked();
                mHandler.postDelayed(mReleaser, timeout);}    异步调用release(),实现延迟释放锁

        acquireLocked()
            -> mService.acquireWakeLock(mFlags, mToken, mTag, mWorkSource);    //调用PMS.acquireWakeLock(int flags, IBinder lock, String tag, WorkSource ws)

        release()    //释放锁
            -> release(int flags)

        release(int flags)
            -> mService.releaseWakeLock(mToken, flags);    //调用PMS.releaseWakeLock(IBinder lock, int flags)

        isHeld()    //返回this.mHeld变量,该变量记录该锁是否被持有

        setWorkSource(WorkSource ws)    //设置该锁作用的worksource
            -> mService.updateWakeLockWorkSource(mToken, mWorkSource);    //调用PMS.updateWakeLockWorkSource(IBinder lock, WorkSource ws)

        finalize() throws Throwable
            -> mService.releaseWakeLock(mToken, 0);        //调用PMS.releaseWakeLock(IBinder lock, int flags)

    }//endl-class.WakeLock    

    WakeLock newWakeLock(int flags, String tag)    //主要用在创建wakelock时,返回一个wakelock
        -> return new WakeLock(flags, tag);

    void userActivity(long when, boolean noChangeLights)    //通知电源管理器发生了用户活动。
        -> mService.userActivity(when, noChangeLights);    //调用PMS.userActivity(when, noChangeLights);
重置自动关闭的计时器,如果设备没有休眠的话点亮屏幕。当按下键盘或者电源键的时候,一般就会发生情况,或者当有一些其它的用户活动发生。如果设备已经休眠了,这个方法不会唤醒设备
    
    void goToSleep(long time)    //Force(强制) the device to go to sleep
        -> mService.goToSleep(time);    //调用PMS.goToSleep(long time)

    void setBacklightBrightness(int brightness)    //
        -> mService.setBacklightBrightness(brightness);    //调用PMS.setBacklightBrightness(brightness);

    int getSupportedWakeLockFlags()
        -> return mService.getSupportedWakeLockFlags();

    boolean isScreenOn()
        -> return mService.isScreenOn();

    void reboot(String reason)
        -> mService.reboot(reason);

    
}//endl-class.PowerManager



PowerManagerService.java

public class PowerManagerService extends IPowerManager.Stub implements LocalPowerManager, Watchdog.Monitor {

    void acquireWakeLock(int flags, IBinder lock, String tag, WorkSource ws)    //该函数为提供给PM的借口,在函数内判断锁的用户id,进程id,进行修改最后恢复。
        -> acquireWakeLockLocked(flags, lock, uid, pid, tag, ws); //调用该函数,PMS的功能函数,主业务之一
        ->{index = mLocks.getIndex(lock); //在PMS内维护一个队列,保存着PM向PMS申请的锁。
        -> if (index < 0)
            ->{wl = new WakeLock(flags, lock, tag, uid, pid); //如果lock不在mLocks队列内,则在PMS内创建一个lock,PM的wl和PMS的wl是对应关系,使用binder来识别。
            -> mLocks.addLock(wl);    //创建的锁加入到mLocks队列内
            -> wl.ws = new WorkSource(ws);         //如果传进来的ws不为空,则需要新建一个ws,赋值给wakelock的ws变量。即:该wakelock作用什么代码上。
        ->}else{
            -> wl = mLocks.get(index);    //如果mLocks内存在传入的lock,则从队列里拿到它。
            -> oldsource = wl.ws;    
            -> diffsource = oldsource.diff(ws);
            -> wl.ws = new WorkSource(ws)    //以上三步为了更新wl.ws变量,中间需要判断该ws是否需要更新。
        -> if (isScreenLock(flags)) {    //如果该锁与锁屏幕有关
            -> if ((flags & LOCK_MASK) == PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK) {
                -> enableProximityLockLocked(); } //该锁为近物感应器关屏锁的话,使能近物感应器
            -> }else{    //不是关于近物感应器关屏幕锁
                -> mWakeLockState = (mUserState | mWakeLockState) & mLocks.gatherState();  }//如果锁不是PM.ACQUIRE_CAUSES_WAKEUP型的话,会计算mWakeLockState
                => setPowerState(mWakeLockState | mUserState); }//关于屏幕的锁,且不与近物感应器相关的锁的话,会调用到这里
        -> else if ((flags & LOCK_MASK) == PowerManager.PARTIAL_WAKE_LOCK)  //之后调用Power.java,再去hal层power.c,power.c写kernel设备节点文件。来控制wakelock
            -> Power.acquireWakeLock(Power.PARTIAL_WAKE_LOCK,PARTIAL_NAME);
        -> if (diffsource) {noteStopWakeLocked(wl, oldsource);}  //ws改变了,就要释放掉上一个ws
        -> if (newlock || diffsource) {noteStartWakeLocked(wl, ws);} //与上一步相反,实际batterystate.noteStartWakelockFromSource,字面上看是通过ws开始wl

    void releaseWakeLock(IBinder lock, int flags)    //该函数提供给PM的接口,释放lock
        -> releaseWakeLockLocked(IBinder lock, int flags, boolean death) //PMS的功能函数,主业务之一
            -> WakeLock wl = mLocks.removeLock(lock);    //直接从PMS的mLocks队列里删除该锁,如果该锁不在队列内直接函数退出
        -> if (isScreenLock(wl.flags))  //该锁与屏幕相关
            -> if ((wl.flags & LOCK_MASK) == PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK)
                -> disableProximityLockLocked(); //如果锁类型为近物感应器关屏幕锁的话,根据感应器状态,该类锁剩余数判断,可能会关闭近物感应器。
        -> else {
            -> mWakeLockState = mLocks.gatherState();  //计算mLocks队列的所有锁的逻辑运算的最终状态。
            => setPowerState(mWakeLockState | mUserState);   //该函数由于多函数调用则特对其进行单独分析。
        -> else if ((wl.flags & LOCK_MASK) == PowerManager.PARTIAL_WAKE_LOCK) //PARTIAL_WAKE_LOCK的处理
            -> Power.releaseWakeLock(PARTIAL_NAME);     //会调用power.java来处理,这里需要此类型的锁在队列里不再存在的话会调用这个。


    void setPowerState(int state)  //被acquireWakeLockLocked、releaseWakeLockLocked和goToSleepLocked调用,设置电源状态
        -> setPowerState(state, false, WindowManagerPolicy.OFF_BECAUSE_OF_TIMEOUT);
        => setPowerState(int newState, boolean noChangeLights, int reason)
            -> newState(新电源状态)、oldScreenOn(屏幕旧状态)、newScreenOn(屏幕新状态)、stateChanged(电源状态是否改变)  
                //根据当前状态判断出这4个变量值,复杂的逻辑运算。不那么详细了。
            -> if (oldScreenOn != newScreenOn) && newScreenOn  //屏幕状态由关状态变成打开状态时
                -> boolean reallyTurnScreenOn = true; //创建个变量初始为true
                -> if (mPreventScreenOn) { reallyTurnScreenOn = false; }  //在亮屏动作之后又出现一个关屏需求,则reallyTurnScreenOn = false;
                -> if (reallyTurnScreenOn) { err = setScreenStateLocked(true);}   //如果需要亮屏,调用setScreenStateLocked(true)
                -> else { setScreenStateLocked(false);  } //如果不需要亮屏,调用setScreenStateLocked(false) 这个函数设计到Power.java函数,独立分析
            -> else if (stateChanged) { //如果不是屏幕变化,而只有电源状态变化
                -> updateLightsLocked(newState, 0);  //更新亮度
            -> mPowerState = (mPowerState & ~LIGHTS_MASK) | (newState & LIGHTS_MASK); //更新PMS内当前电源状态
            -> updateNativePowerStateLocked();        //在将native层电源状态记录的变量值进行一下更新。上下统一,在每层都有电源状态变量,锁在PMS,kernel都有队列进行维护
            
    int setScreenStateLocked(boolean on)  //通过Power.java设置屏幕状态
        -> Power.setScreenState(on);    //power.java文件说明内有详解


    void updateWakeLockWorkSource(IBinder lock, WorkSource ws) //更新wakelock的worksource
        -> int index = mLocks.getIndex(lock); 获得锁的索引
        -> WakeLock wl = mLocks.get(index);     获得锁
        -> WorkSource oldsource = wl.ws; 获得ws
        -> wl.ws = ws != null ? new WorkSource(ws) : null; ws不空则创建新ws给锁
        -> noteStopWakeLocked(wl, oldsource); //释放上一个ws
        -> noteStartWakeLocked(wl, ws);  

    提供给PM的接口函数:通知电源管理器发生了用户活动。
    重置自动关闭的计时器,如果设备没有休眠的话点亮屏幕。当按下键盘或者电源键的时候,一般就会发生情况,或者当有一些其它的用户活动发生。如果设备已经休眠了,这个方法不会唤醒设备。
    需要DEVICE_POWER权限。                
    void userActivity(long time, long timeoutOverride, boolean noChangeLights,int eventType, boolean force)

    提供给PM的接口函数:强迫设备进入休眠。
    覆盖所有正在被使用的wake lock。当按下电源键关闭屏幕的时候,这个方法会被调用。
    需要DEVICE_POWER权限。
    void goToSleep(long time)
        -> goToSleepWithReason(long time, int reason)
            -> goToSleepLocked(time, reason);
                -> setPowerState(SCREEN_OFF, false, reason);

    提供给PM的接口函数:设置背光亮度
    void setBacklightBrightness(int brightness)

    提供给PM的接口函数:获取当前屏幕是否打开
    boolean isScreenOn()    //
        -> return (mPowerState & SCREEN_ON_BIT) != 0;
    


}//endl-PowerManagerService-class







power.java:
native void acquireWakeLock(int lock, String id)
    -> acquireWakeLock(JNIEnv *env, jobject clazz, jint lock, jstring idObj)@android_os_Power.cpp
    -> acquire_wake_lock(lock, id)
    -> write("/sys/power/wake_lock", "PowerManagerService", strlen(PowerManagerService))
    -> kernel::wake_lock_store(struct kobject *kobj, struct kobj_attribute *attr,const char *buf, size_t n)    @userwakelock.c
        -> l = lookup_wake_lock_name(buf, 1, &timeout); 获得指定的唤醒锁,从user_wake_lock二叉树获取user_wake_lock,链表节点包括wake_lock. 如果能在二叉树上查找到buf内信息的user_wake_lock,则返回该锁,否则创建一个新user_wake_lock,将该锁初始化,返回该锁。
        -> if (timeout) wake_lock_timeout(&l->wake_lock, timeout); 如果是延迟锁
            -> else wake_lock(&l->wake_lock);  不是延迟锁
            => static void wake_lock_internal(struct wake_lock *lock, long timeout, int has_timeout) 先处理下lock.state内的值
            -> list_del(&lock->link);wake_lock由一个链表维护,先从链表删除,新创建的wake_lock其实是自己算一个队列,删除他对他没有影响
            -> if (has_timeout) list_add_tail(&lock->link, &active_wake_locks[type]); 超时锁加队尾
            -> else list_add(&lock->link, &active_wake_locks[type]);  非超时锁加队首
            -> if (type == WAKE_LOCK_SUSPEND) && (lock == &main_wake_lock)  update_sleep_wait_stats_locked(1);
            -> if (type == WAKE_LOCK_SUSPEND) && (!wake_lock_active(&main_wake_lock)) update_sleep_wait_stats_locked(0);
            -> if (type == WAKE_LOCK_SUSPEND) && (has_timeout) expire_in = has_wake_lock_locked(type); 获取是否有type类型的锁,
            -> if (expire_in > 0) mod_timer(&expire_timer, jiffies + expire_in); 如果有expire_in,及有type类型的锁,设置新的时间给定时器expire_timer
                -> expire_wake_locks(unsigned long data) 定时器结束处理函数:先查看active_wake_locks队列内是否有WAKE_LOCK_SUSPEND类型锁,
                -> 如果没有,queue_work(suspend_work_queue, &suspend_work);
                -> 实际上调用suspend(struct work_struct *work) @wakelock.c
                -> enter_state(suspend_state_t state)调用到此,进入标准linux睡眠流程


native void releaseWakeLock(String id)
    -> releaseWakeLock(JNIEnv *env, jobject clazz, jstring idObj)
    -> release_wake_lock(id);
    -> write("/sys/power/wake_unlock", "PowerManagerService", strlen(PowerManagerService));
    -> kernel::wake_unlock_store(struct kobject *kobj, struct kobj_attribute *attr,const char *buf, size_t n)    @userwakelock.c
    -> l = lookup_wake_lock_name(buf, 0, NULL); //user_wake_lock二叉树获取user_wake_lock,buf内存有user_wake_lock的名字,查找到之后返回,如果没有,新建一个,初始化,返回
    -> wake_unlock(&l->wake_lock);释放l节点上的wake_lock
        -> type = lock->flags & WAKE_LOCK_TYPE_MASK; //获得lock类型
        -> lock->flags &= ~(WAKE_LOCK_ACTIVE | WAKE_LOCK_AUTO_EXPIRE); //修改lock类型
        -> list_del(&lock->link); list_add(&lock->link, &inactive_locks); //lock从active_locks队列删除,添加到inactive_locks队列。
            -> long has_lock = has_wake_lock_locked(type); 看看还有没有超时锁,函数内,会用每个锁的超时时间与一个数相减,根据结果决定每个锁是否是要释放。或者有锁的时间比当前最大超时时间大,则从新设最大超时时间,如果有非超时锁(这种情况可能存在超时锁或不存在超时锁都可以),返回-1
            -> if (type == WAKE_LOCK_SUSPEND) && (has_lock > 0) mod_timer(&expire_timer, jiffies + has_lock);
                -> expire_wake_locks(unsigned long data) 定时器结束处理函数:先查看active_wake_locks队列内是否有WAKE_LOCK_SUSPEND类型锁,
                -> 如果没有,queue_work(suspend_work_queue, &suspend_work);
                -> 实际上调用suspend(struct work_struct *work) @wakelock.c
                -> enter_state(suspend_state_t state)调用到此,进入标准linux睡眠流程
            -> if (type == WAKE_LOCK_SUSPEND) && (has_lock == -1) 上面返回-1, 调用del_timer(&expire_timer) 所以没有锁都不是超时锁的话,定时器就没用了,删除之。
            -> if (type == WAKE_LOCK_SUSPEND) && (has_lock == 0) queue_work(suspend_work_queue, &suspend_work);没有非超时锁,且超时锁都被释放时,会调用
            -> 实际上调用suspend(struct work_struct *work) @wakelock.c
            -> enter_state(suspend_state_t state)调用到此,进入标准linux睡眠流程



native int setScreenState(boolean on)
    -> setScreenState(JNIEnv *env, jobject clazz, jboolean on)
    -> set_screen_state(on)
    -> write("/sys/power/state", buf, len);
    -> kernel::state_store(struct kobject *kobj, struct kobj_attribute *attr,const char *buf, size_t n)
    -> request_suspend_state(state) 下面有说明


native int setLastUserActivityTimeout(long ms)  //只在创建pms时调用过一次,设置超时时间1周
    -> setLastUserActivityTimeout(JNIEnv *env, jobject clazz, jlong timeMS)
    -> set_last_user_activity_timeout(int64_t delay)
    -> write("/sys/android_power/auto_off_timeout", timeMS/1000, len(timeMS/1000));

native void shutdown() --> android_reboot(ANDROID_RB_POWEROFF, 0, 0);
native void rebootNative(String reason) throws IOException --> android_reboot(ANDROID_RB_RESTART2, 0, (char *) chars);


kernel:
early_suspend 和 标准linux suspend:摘自blog.csdn.net/g_salamander/article/details/7982170
如何进入early_suspend流程?
当向/sys/power/state文件内写入数据是,state_store()函数会被掉用。这样才会有可能进入early_suspend或者suspend流程。
进入early_suspend流程的函数是request_suspend_state(state);//如果定义了CONFIG_EARLYSUSPEND宏,则android将会执行调用这个函数否则会调用enter_state(state);//标准Linux将调用,android将会执行调用request_suspend_state(state);
request_suspend_state(state):
    // 如果新状态是休眠状态  
    if (!old_sleep && new_state != PM_SUSPEND_ON) {  
        state |= SUSPEND_REQUESTED;  
        pr_info("sys_sync_work_queue early_sys_sync_work.\n");  
        queue_work(suspend_work_queue, &early_suspend_work);  
    } else if (old_sleep && new_state == PM_SUSPEND_ON) {  
    // 如果新状态是唤醒状态  
        state &= ~SUSPEND_REQUESTED;  
        // 激活内核锁  
        wake_lock(&main_wake_lock);  
        // 执行浅度唤醒的工作队列  
        queue_work(suspend_work_queue, &late_resume_work);  
    }  
    // 更新全局状态  
    requested_suspend_state = new_state;  
如果是休眠状态则置位SUSPEND_REQUESTED标志,然后将同步缓存、浅度休眠工作队列加入相应的内核线程执行;如果新状态是唤醒则首先将main_wake_lock激活,然后再将浅度唤醒工作队列加入内核线程执行;最后更新全局状态变量,因为提供了一个内核空间接口用于获取当前休眠唤醒状态:
static DECLARE_WORK(early_suspend_work, early_suspend);

early_suspend:
     static void early_suspend(struct work_struct *work)  
    {  
        struct early_suspend *pos;  
        unsigned long irqflags;  
        int abort = 0;  
      
        mutex_lock(&early_suspend_lock);  
        spin_lock_irqsave(&state_lock, irqflags);  
        if (state == SUSPEND_REQUESTED)  // 判断当前状态是否在请求浅度休眠  
            state |= SUSPENDED;      // 如果是则置位SUSPENDED  
        else  
            abort = 1;  
        spin_unlock_irqrestore(&state_lock, irqflags);  
      
        if (abort) {  // 取消early_suspend  
            if (debug_mask & DEBUG_SUSPEND)  
                pr_info("early_suspend: abort, state %d\n", state);  
            mutex_unlock(&early_suspend_lock);  
            goto abort;  
        }  
      
        if (debug_mask & DEBUG_SUSPEND)  
            pr_info("early_suspend: call handlers\n");  
        // 遍历浅度休眠链表并执行其中所有suspend函数  
        // 执行顺序根据优先等级而定,等级越低越先执行  
        list_for_each_entry(pos, &early_suspend_handlers, link) {  
            if (pos->suspend != NULL)  //遍历浅度休眠链表,从链表头部到尾部依次调用各节点的suspend()函数
                pos->suspend(pos);  
        }  
        mutex_unlock(&early_suspend_lock);  
      
        if (debug_mask & DEBUG_SUSPEND)  
            pr_info("early_suspend: sync\n");  
      
        /* Remove sys_sync from early_suspend, and use work queue to complete sys_sync */  
        //sys_sync();  
    abort:  
        spin_lock_irqsave(&state_lock, irqflags);  
        if (state == SUSPEND_REQUESTED_AND_SUSPENDED)  
            wake_unlock(&main_wake_lock);  
        spin_unlock_irqrestore(&state_lock, irqflags);  
    }  
在suspend流程中首先判断当前状态是否为SUSPEND_REQUESTED,如果是则置位SUSPENDED标志,如果不是则取消suspend流程;然后遍历浅度休眠链表,从链表头部到尾部依次调用各节点的suspend()函数,执行完后判断当前状态是否为SUSPEND_REQUESTED_AND_SUSPENDED,如果是则释放main_wake_lock,当前系统中如果只存在main_wake_lock这个有效锁,则会在wake_unlock()里面启动深度休眠线程,如果还有其他其他wake_lock则保持当前状态。

late_resume:
    static void late_resume(struct work_struct *work)  
    {  
        struct early_suspend *pos;  
        unsigned long irqflags;  
        int abort = 0;  
      
        mutex_lock(&early_suspend_lock);  
        spin_lock_irqsave(&state_lock, irqflags);  
        if (state == SUSPENDED)  // 清除浅度休眠完成标志  
            state &= ~SUSPENDED;  
        else  
            abort = 1;  
        spin_unlock_irqrestore(&state_lock, irqflags);  
      
        if (abort) {  
            if (debug_mask & DEBUG_SUSPEND)  
                pr_info("late_resume: abort, state %d\n", state);  
            goto abort;  
        }  
        if (debug_mask & DEBUG_SUSPEND)  
            pr_info("late_resume: call handlers\n");  
        // 反向遍历浅度休眠链表并执行其中所有resume函数  
        // 执行顺序根据优先等级而定,等级越高越先执行  
        list_for_each_entry_reverse(pos, &early_suspend_handlers, link)  
            if (pos->resume != NULL)  
                pos->resume(pos);  
        if (debug_mask & DEBUG_SUSPEND)  
            pr_info("late_resume: done\n");  
    abort:  
        mutex_unlock(&early_suspend_lock);  
    }  
在resume流程中同样首先判断当前状态是否为SUSPENDED,如果是则清除SUSPENDED标志,然后反向遍历浅度休眠链表,按照优先等级从高到低的顺序执行节点的resume()函数。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值