700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > Android4.4电源管理——电源锁

Android4.4电源管理——电源锁

时间:2020-05-20 18:31:30

相关推荐

Android4.4电源管理——电源锁

//创建电源锁

[cpp]view plain copy

PowerManagerService.java

mWakeLockSuspendBlocker = createSuspendBlockerLocked("PowerManagerService.WakeLocks");

mDisplaySuspendBlocker = createSuspendBlockerLocked("PowerManagerService.Display");

private SuspendBlocker createSuspendBlockerLocked(String name) {

SuspendBlocker suspendBlocker = new SuspendBlockerImpl(name);

mSuspendBlockers.add(suspendBlocker);

return suspendBlocker;

}

//电源锁操作类的实现

[cpp]view plain copy

private final class SuspendBlockerImpl implements SuspendBlocker {

private final String mName;

private int mReferenceCount;

public SuspendBlockerImpl(String name) {

mName = name;

}

@Override

public void acquire() {

synchronized (this) {

mReferenceCount += 1;

if (mReferenceCount == 1) {

if (DEBUG_SPEW) {

Slog.d(TAG, "Acquiring suspend blocker \"" + mName + "\".");

}

nativeAcquireSuspendBlocker(mName);

}

}

}

@Override

public void release() {

synchronized (this) {

mReferenceCount -= 1;

if (mReferenceCount == 0) {

if (DEBUG_SPEW) {

Slog.d(TAG, "Releasing suspend blocker \"" + mName + "\".");

}

nativeReleaseSuspendBlocker(mName);

} else if (mReferenceCount < 0) {

Log.wtf(TAG, "Suspend blocker \"" + mName

+ "\" was released without being acquired!", new Throwable());

mReferenceCount = 0;

}

}

}

}

//JNI层函数实现电源锁的获取

[cpp]view plain copy

com_android_server_power_PowerManagerService.cpp

static void nativeAcquireSuspendBlocker(JNIEnv *env, jclass clazz, jstring nameStr) {

ScopedUtfChars name(env, nameStr);

acquire_wake_lock(PARTIAL_WAKE_LOCK, name.c_str());

}

//将电源锁写入到相应的文件中,相当于获得了电源锁

power.c

[cpp]view plain copy

int acquire_wake_lock(int lock, const char* id)

{

initialize_fds();

if (g_error) return g_error;

int fd;

if (lock == PARTIAL_WAKE_LOCK) {

fd = g_fds[ACQUIRE_PARTIAL_WAKE_LOCK];

}

else {

return EINVAL;

}

return write(fd, id, strlen(id));

}

//打开记录电源锁的文件

[cpp]view plain copy

static inline void

initialize_fds(void)

{

if (g_initialized == 0) {

if(open_file_descriptors(NEW_PATHS) < 0)

open_file_descriptors(OLD_PATHS);

g_initialized = 1;

}

}

//记录电源锁的文件路径

[cpp]view plain copy

const char * const OLD_PATHS[] = {

"/sys/android_power/acquire_partial_wake_lock",

"/sys/android_power/release_wake_lock",

};

const char * const NEW_PATHS[] = {

"/sys/power/wake_lock",

"/sys/power/wake_unlock",

};

到现在为止,我们的代码流程已经走了一大半了,我们一开始介绍的android的上面几层Framework层、JNI层、HAL层都已经介绍了。下面就应该是和kernel层进行交互了。

但是在android/hardware/libhardware_legacy/power/power.c中的acquire_wake_lock()函数似乎没法和kernel层进行通信啊?最后的返回语句return write(fd, id, strlen(id))是一个系统调用,这里就实现了与kernel的交互。

kernel/power/main.c中的power_attr宏很多地方用到:

[cpp]view plain copy#definepower_attr(_name)\staticstructkobj_attribute_name##_attr={\.attr={\.name=__stringify(_name),\.mode=0644,\},\.show=_name##_show,\.store=_name##_store,\}[cpp]view plain copy#ifdefCONFIG_USER_WAKELOCKpower_attr(wake_lock);power_attr(wake_unlock);#endif default y

User-space wake lock api. Write "lockname" or "lockname timeout"

to /sys/power/wake_lock lock and if needed create a wake lock.

Write "lockname" to /sys/power/wake_unlock to unlock a user wake

lock.

[cpp]view plain copy#ifdefCONFIG_PM_WAKELOCKSpower_attr(wake_lock);power_attr(wake_unlock);#endif default n

Allow user space to create, activate and deactivate wakeup source

objects with the help of a sysfs-based interface.

宏展开,等价于:

[cpp]view plain copystaticstructkobj_attributewake_lock_attr={.attr={.name=“wake_lock”,.mode=0644,},.show=wake_lock_show,.store=wake_lock_store,}[cpp]view plain copystaticstructkobj_attributewake_unlock_attr={.attr={.name=“wake_unlock”,.mode=0644,},.show=wake_unlock_show,.store=wake_unlock_store,} show和store函数的源码位于kernel/power/userwakelock.c。

[cpp]view plain copystaticstructattribute*g[]={&state_attr.attr,#ifdefCONFIG_PM_TRACE&pm_trace_attr.attr,&pm_trace_dev_match_attr.attr,#endif#ifdefCONFIG_PM_SLEEP&pm_async_attr.attr,&wakeup_count_attr.attr,#ifdefCONFIG_USER_WAKELOCK&wake_lock_attr.attr,&wake_unlock_attr.attr,#endif#ifdefCONFIG_PM_AUTOSLEEP&autosleep_attr.attr,#endif#ifdefCONFIG_PM_WAKELOCKS&wake_lock_attr.attr,&wake_unlock_attr.attr,#endif#ifdefCONFIG_PM_DEBUG&pm_test_attr.attr,#endif#ifdefCONFIG_PM_SLEEP_DEBUG&pm_print_times_attr.attr,#endif#endif#ifdefCONFIG_FREEZER&pm_freeze_timeout_attr.attr,#endifNULL,};[cpp]view plain copystaticstructattribute_groupattr_group={.attrs=g,}; pm_init()->

error = sysfs_create_group(power_kobj, &attr_group);

好了,我们该回到原来我们产生疑问的地方了这时我们还得关注其中的另一个函数acquire_wake_lock()->initialize_fds()。[cpp]view plain copyinitialize_fds(void){//XXX:shouldbethis://pthread_once(&g_initialized,open_file_descriptors);//XXX:notthis:if(g_initialized==0){if(open_file_descriptors(NEW_PATHS)<0)open_file_descriptors(OLD_PATHS);g_initialized=1;}}

其实这个函数中最核心的步骤就是open_file_descriptors(NEW_PATHS),顺序打开NEW_PATHS[ ]中的文件:

[cpp]view plain copystaticintopen_file_descriptors(constchar*constpaths[]){inti;for(i=0;i<OUR_FD_COUNT;i++){intfd=open(paths[i],O_RDWR);if(fd<0){fprintf(stderr,"fatalerroropening\"%s\"\n",paths[i]);g_error=errno;return-1;}g_fds[i]=fd;}g_error=0;return0;}[cpp]view plain copy constchar*constNEW_PATHS[]={"/sys/power/wake_lock","/sys/power/wake_unlock",};

总之经过着一系列的步骤后,最终我们将在 return write(fd, id, strlen(id));时调用android/kernel/kernel/power/userwakelock.c 中的 wake_lock_store()函数。

[cpp]view plain copy ssize_twake_lock_store(structkobject*kobj,structkobj_attribute*attr,constchar*buf,size_tn){longtimeout;structuser_wake_lock*l;mutex_lock(&tree_lock);l=lookup_wake_lock_name(buf,1,&timeout);if(IS_ERR(l)){n=PTR_ERR(l);gotobad_name;}if(debug_mask&DEBUG_ACCESS)pr_info("wake_lock_store:%s,timeout%ld\n",l->name,timeout);if(timeout)wake_lock_timeout(&l->wake_lock,timeout);elsewake_lock(&l->wake_lock);bad_name:mutex_unlock(&tree_lock);returnn;}[cpp]view plain copy structrb_rootuser_wake_locks;staticstructuser_wake_lock*lookup_wake_lock_name(constchar*buf,intallocate,long*timeoutptr){structrb_node**p=&user_wake_locks.rb_node;structrb_node*parent=NULL;structuser_wake_lock*l;intdiff;u64timeout;intname_len;constchar*arg;/*Findlengthoflocknameandstartofoptionaltimeoutstring*/arg=buf;while(*arg&&!isspace(*arg))arg++;//lockname的长度name_len=arg-buf;if(!name_len)gotobad_arg;while(isspace(*arg))arg++;/*Processtimeoutstring*/if(timeoutptr&&*arg){//(char**)&arg存储的是解析string的结束字符timeout=simple_strtoull(arg,(char**)&arg,0);while(isspace(*arg))arg++;//如果解析string的结束字符不是’\0’if(*arg)gotobad_arg;/*converttimeoutfromnanosecondstojiffies>0*/timeout+=(NSEC_PER_SEC/HZ)-1;//do_div(a,b)的返回值是余数,商保存到a中do_div(timeout,(NSEC_PER_SEC/HZ));if(timeout<=0)timeout=1;*timeoutptr=timeout;}elseif(*arg)//timeoutptr为NULLgotobad_arg;elseif(timeoutptr)//*arg为0,没有timeout*timeoutptr=0;/*Lookupwakelockinrbtree*///对于一颗空的红黑树,略过while。wakelock按照name从小到大的顺序存储到user_wake_locks红黑树中while(*p){parent=*p;l=rb_entry(parent,structuser_wake_lock,node);diff=strncmp(buf,l->name,name_len);//如果buf是l->name的子串,那么l->name[name_len]就不会为0,但是buf[name_len]会为0if(!diff&&l->name[name_len])diff=-1;if(debug_mask&DEBUG_ERROR)pr_info("lookup_wake_lock_name:compare%.*s%s%d\n",name_len,buf,l->name,diff);if(diff<0)p=&(*p)->rb_left;elseif(diff>0)p=&(*p)->rb_right;elsereturnl;}/*Allocateandaddnewwakelocktorbtree*///allocate为0,表示不需要分配新的wakelock,只在rbtree上查找,找不到就出错了if(!allocate){if(debug_mask&DEBUG_ERROR)pr_info("lookup_wake_lock_name:%.*snotfound\n",name_len,buf);returnERR_PTR(-EINVAL);}l=kzalloc(sizeof(*l)+name_len+1,GFP_KERNEL);if(l==NULL){if(debug_mask&DEBUG_FAILURE)pr_err("lookup_wake_lock_name:failedtoallocate""memoryfor%.*s\n",name_len,buf);returnERR_PTR(-ENOMEM);}memcpy(l->name,buf,name_len);if(debug_mask&DEBUG_NEW)pr_info("lookup_wake_lock_name:newwakelock%s\n",l->name);wake_lock_init(&l->wake_lock,WAKE_LOCK_SUSPEND,l->name);//插入结点,并染成红色rb_link_node(&l->node,parent,p);rb_insert_color(&l->node,&user_wake_locks);returnl;bad_arg:if(debug_mask&DEBUG_ERROR)pr_info("lookup_wake_lock_name:wakelock,%.*s,badarg,%s\n",name_len,buf,arg);returnERR_PTR(-EINVAL);}

wake_lock_store()执行的基本流程为:首先调用lookup_wake_lock_name()来获得指定的唤醒锁,若延迟参数timeout为零的话,就调用 wake_lock()否则就调用wake_lock_timeout(),但不管调用哪个最后都会调用到android/kernel/kernel/power/wakelock.c中的函数static void wake_lock_internal()。

[cpp]view plain copy staticvoidwake_lock_internal(structwake_lock*lock,longtimeout,inthas_timeout){inttype;unsignedlongirqflags;longexpire_in;spin_lock_irqsave(&list_lock,irqflags);type=lock->flags&WAKE_LOCK_TYPE_MASK;//检查type是否合法BUG_ON(type>=WAKE_LOCK_TYPE_COUNT);//检查是否初始化过BUG_ON(!(lock->flags&WAKE_LOCK_INITIALIZED));#ifdefCONFIG_WAKELOCK_STATif(type==WAKE_LOCK_SUSPEND&&wait_for_wakeup){if(debug_mask&DEBUG_WAKEUP)pr_info("wakeupwakelock:%s\n",lock->name);wait_for_wakeup=0;lock->stat.wakeup_count++;}if((lock->flags&WAKE_LOCK_AUTO_EXPIRE)&&(long)(lock->expires-jiffies)<=0){wake_unlock_stat_locked(lock,0);lock->stat.last_time=ktime_get();}#endifif(!(lock->flags&WAKE_LOCK_ACTIVE)){lock->flags|=WAKE_LOCK_ACTIVE;#ifdefCONFIG_WAKELOCK_STATlock->stat.last_time=ktime_get();#endif}//从inactive_locks上删除list_del(&lock->link);if(has_timeout){if(debug_mask&DEBUG_WAKE_LOCK)pr_info("wake_lock:%s,type%d,timeout%ld.%03lu\n",lock->name,type,timeout/HZ,(timeout%HZ)*MSEC_PER_SEC/HZ);lock->expires=jiffies+timeout;lock->flags|=WAKE_LOCK_AUTO_EXPIRE;list_add_tail(&lock->link,&active_wake_locks[type]);}else{if(debug_mask&DEBUG_WAKE_LOCK)pr_info("wake_lock:%s,type%d\n",lock->name,type);lock->expires=LONG_MAX;lock->flags&=~WAKE_LOCK_AUTO_EXPIRE;list_add(&lock->link,&active_wake_locks[type]);}if(type==WAKE_LOCK_SUSPEND){current_event_num++;#ifdefCONFIG_WAKELOCK_STATif(lock==&main_wake_lock)update_sleep_wait_stats_locked(1);elseif(!wake_lock_active(&main_wake_lock))update_sleep_wait_stats_locked(0);#endifif(has_timeout)expire_in=has_wake_lock_locked(type);elseexpire_in=-1;if(expire_in>0){if(debug_mask&DEBUG_EXPIRE)pr_info("wake_lock:%s,startexpiretimer,""%ld\n",lock->name,expire_in);mod_timer(&expire_timer,jiffies+expire_in);}else{if(del_timer(&expire_timer))if(debug_mask&DEBUG_EXPIRE)pr_info("wake_lock:%s,stopexpiretimer\n",lock->name);if(expire_in==0)queue_work(suspend_work_queue,&suspend_work);}}spin_unlock_irqrestore(&list_lock,irqflags);}

//电源锁的使用

[cpp]view plain copy

/**

* 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;

}

}

//判断是否处于亮屏或者正在变化阶段

[cpp]view plain copyprivate boolean needDisplaySuspendBlocker() {

//正处于变化阶段

if (!mDisplayReady) {

return true;

}

if (mDisplayPowerRequest.screenState != DisplayPowerRequest.SCREEN_STATE_OFF) {

//有疑问?

// If we asked for the screen to be on but it is off due to the proximity

// sensor then we may suspend but only if the configuration allows it.

// On some hardware it may not be safe to suspend because the proximity

// sensor may not be correctly configured as a wake-up source.

if (!mDisplayPowerRequest.useProximitySensor || !mProximityPositive

|| !mSuspendWhenScreenOffDueToProximityConfig) {

return true;

}

}

return false;

}

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。