在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()函数。
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()函数。