码迷,mamicode.com
首页 > 移动开发 > 详细

Android休眠唤醒机制简介(二)

时间:2017-10-11 15:33:01      阅读:380      评论:0      收藏:0      [点我收藏+]

标签:row   not   分配   nat   系统调用   blog   lag   流程   access   

本文转载自:http://blog.csdn.net/zhaoxiaoqiang10_/article/details/24408911

Android休眠唤醒机制简介(二)
******************************************************************
作者:sean
日期:2012-11-29
修改历史:2014-1
******************************************************************
接上一节,结合code来分析一下:

 

具体流程

下面我将分别以两条路线(第一:获得wakelock唤醒锁。第二:系统进入睡眠。)来分别说明各自的流程,让读者对android睡眠唤醒机制有更深入的理解!

第一部分:获得wakelock唤醒锁

比如在应用程序中,当获得wakelock唤醒锁的时候,它首先是调用frameworks/base/core/java/android/os/PowerManager.java类中的public void acquire()方法,而该方法通过android特有的通讯机制,会接着调用到PowerManagerService类中的public void acquireWakeLock。

 

[cpp] view plaincopy技术分享技术分享
 
 
  1. public void acquire() {  
  2.     synchronized (mToken) {  
  3.         acquireLocked();  
  4.     }  
  5. }  
[cpp] view plaincopy技术分享技术分享
 
 
  1. private void acquireLocked() {  
  2.     if (!mRefCounted || mCount++ == 0) {  
  3.         // Do this even if the wake lock is already thought to be held (mHeld == true)  
  4.         // because non-reference counted wake locks are not always properly released.  
  5.         // For example, the keyguard‘s wake lock might be forcibly released by the  
  6.         // power manager without the keyguard knowing.  A subsequent call to acquire  
  7.         // should immediately acquire the wake lock once again despite never having  
  8.         // been explicitly released by the keyguard.  
  9.         mHandler.removeCallbacks(mReleaser);  
  10.         try {  
  11.             mService.acquireWakeLock(mToken, mFlags, mTag, mPackageName, mWorkSource);  
  12.         } catch (RemoteException e) {  
  13.         }  
  14.         mHeld = true;  
  15.     }  
  16. }  
[cpp] view plaincopy技术分享技术分享
 
 
  1. @Override // Binder call  
  2. public void acquireWakeLock(IBinder lock, int flags, String tag, String packageName,  
  3.         WorkSource ws) {  
  4.     if (lock == null) {  
  5.         throw new IllegalArgumentException("lock must not be null");  
  6.     }  
  7.     if (packageName == null) {  
  8.         throw new IllegalArgumentException("packageName must not be null");  
  9.     }  
  10.     PowerManager.validateWakeLockParameters(flags, tag);  
  11.   
  12.     mContext.enforceCallingOrSelfPermission(android.Manifest.permission.WAKE_LOCK, null);  
  13.     if (ws != null && ws.size() != 0) {  
  14.         mContext.enforceCallingOrSelfPermission(  
  15.                 android.Manifest.permission.UPDATE_DEVICE_STATS, null);  
  16.     } else {  
  17.         ws = null;  
  18.     }  
  19.   
  20.     final int uid = Binder.getCallingUid();  
  21.     final int pid = Binder.getCallingPid();  
  22.     final long ident = Binder.clearCallingIdentity();  
  23.     try {  
  24.         acquireWakeLockInternal(lock, flags, tag, packageName, ws, uid, pid);  
  25.     } finally {  
  26.         Binder.restoreCallingIdentity(ident);  
  27.     }  
  28. }  

 

acquireWakeLockInternal()->updatePowerStateLocked()->updateSuspendBlockerLocked()->

 

[cpp] view plaincopy技术分享技术分享
 
 
  1. private void updateSuspendBlockerLocked() {  
  2.     final boolean needWakeLockSuspendBlocker = ((mWakeLockSummary & WAKE_LOCK_CPU) != 0);  
  3.     final boolean needDisplaySuspendBlocker = needDisplaySuspendBlocker();  
  4.   
  5.     // First acquire suspend blockers if needed.  
  6.     if (needWakeLockSuspendBlocker && !mHoldingWakeLockSuspendBlocker) {  
  7.         mWakeLockSuspendBlocker.acquire();  
  8.         mHoldingWakeLockSuspendBlocker = true;  
  9.     }  
  10.     if (needDisplaySuspendBlocker && !mHoldingDisplaySuspendBlocker) {  
  11.         mDisplaySuspendBlocker.acquire();  
  12.         mHoldingDisplaySuspendBlocker = true;  
  13.     }  
  14.   
  15.     // Then release suspend blockers if needed.  
  16.     if (!needWakeLockSuspendBlocker && mHoldingWakeLockSuspendBlocker) {  
  17.         mWakeLockSuspendBlocker.release();  
  18.         mHoldingWakeLockSuspendBlocker = false;  
  19.     }  
  20.     if (!needDisplaySuspendBlocker && mHoldingDisplaySuspendBlocker) {  
  21.         mDisplaySuspendBlocker.release();  
  22.         mHoldingDisplaySuspendBlocker = false;  
  23.     }  
  24. }  
acquire()是什么函数?需要看一下frameworks/base/services/java/com/android/server/PowerManagerService.java类的构造过程。

 

 

[cpp] view plaincopy技术分享技术分享
 
 
  1. public PowerManagerService() {  
  2.      synchronized (mLock) {  
  3.          mWakeLockSuspendBlocker = createSuspendBlockerLocked("PowerManagerService.WakeLocks");  
  4.          mDisplaySuspendBlocker = createSuspendBlockerLocked("PowerManagerService.Display");  
  5.          mDisplaySuspendBlocker.acquire();  
  6.          mHoldingDisplaySuspendBlocker = true;  
  7.   
  8.          mScreenOnBlocker = new ScreenOnBlockerImpl();  
  9.          mDisplayBlanker = new DisplayBlankerImpl();  
  10.          mWakefulness = WAKEFULNESS_AWAKE;  
  11.      }  
  12.   
  13.      nativeInit();  
  14.      nativeSetPowerState(true, true);  
  15.  }  

 

[cpp] view plaincopy
 
 
  1. private SuspendBlocker createSuspendBlockerLocked(String name) {  
  2.     SuspendBlocker suspendBlocker = new SuspendBlockerImpl(name);  
  3.     mSuspendBlockers.add(suspendBlocker);  
  4.     return suspendBlocker;  
  5. }  

 


 

于是frameworks/base/services/java/com/android/server/PowerManagerService.java类的SuspendBlockerImpl类中的acquire(),便是我们要找的acquire()。

 

[cpp] view plaincopy技术分享技术分享
 
 
  1. @Override  
  2. public void acquire() {  
  3.     synchronized (this) {  
  4.         mReferenceCount += 1;  
  5.         if (mReferenceCount == 1) {  
  6.             if (DEBUG_SPEW) {  
  7.                 Slog.d(TAG, "Acquiring suspend blocker \"" + mName + "\".");  
  8.             }  
  9.             nativeAcquireSuspendBlocker(mName);  
  10.         }  
  11.     }  
  12. }  

 

而该方法调用了com_android_server_power_PowerManagerService.cpp中的nativeAcquireSuspendBlocker。
[cpp] view plaincopy技术分享技术分享
 
 
  1. static JNINativeMethod gPowerManagerServiceMethods[] = {  
  2.     /* name, signature, funcPtr */  
  3.     { "nativeInit", "()V",  
  4.             (void*) nativeInit },  
  5.     { "nativeSetPowerState", "(ZZ)V",  
  6.             (void*) nativeSetPowerState },  
  7.     { "nativeAcquireSuspendBlocker", "(Ljava/lang/String;)V",  
  8.             (void*) nativeAcquireSuspendBlocker },  
  9.     { "nativeReleaseSuspendBlocker", "(Ljava/lang/String;)V",  
  10.             (void*) nativeReleaseSuspendBlocker },  
  11.     { "nativeSetInteractive", "(Z)V",  
  12.             (void*) nativeSetInteractive },  
  13.     { "nativeSetAutoSuspend", "(Z)V",  
  14.             (void*) nativeSetAutoSuspend },  
  15. };  
[cpp] view plaincopy技术分享技术分享
 
 
  1. static void nativeAcquireSuspendBlocker(JNIEnv *env, jclass clazz, jstring nameStr) {  
  2.     ScopedUtfChars name(env, nameStr);  
  3.     acquire_wake_lock(PARTIAL_WAKE_LOCK, name.c_str());  
  4. }  
函数 acquire_wake_lock()的实现在 power.c中,其定义如下:
[cpp] view plaincopy技术分享技术分享
 
 
  1. int  
  2. acquire_wake_lock(int lock, const char* id)  
  3. {  
  4.     initialize_fds();  
  5.   
  6. //    ALOGI("acquire_wake_lock lock=%d id=‘%s‘\n", lock, id);  
  7.   
  8.     if (g_error) return g_error;  
  9.   
  10.     int fd;  
  11.   
  12.     if (lock == PARTIAL_WAKE_LOCK) {  
  13.         fd = g_fds[ACQUIRE_PARTIAL_WAKE_LOCK];  
  14.     }  
  15.     else {  
  16.         return EINVAL;  
  17.     }  
  18.   
  19.     return write(fd, id, strlen(id));  
  20. }  
到现在为止,我们的代码流程已经走了一大半了,我们一开始介绍的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 plaincopy技术分享技术分享
 
 
  1. #define power_attr(_name) \  
  2. static struct kobj_attribute _name##_attr = {   \  
  3.     .attr   = {             \  
  4.         .name = __stringify(_name), \  
  5.         .mode = 0644,           \  
  6.     },                  \  
  7.     .show   = _name##_show,         \  
  8.     .store  = _name##_store,        \  
  9. }  
[cpp] view plaincopy技术分享技术分享
 
 
  1. #ifdef CONFIG_USER_WAKELOCK  
  2. power_attr(wake_lock);  
  3. power_attr(wake_unlock);  
  4. #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 plaincopy技术分享技术分享
 
 
  1. #ifdef CONFIG_PM_WAKELOCKS  
  2. power_attr(wake_lock);  
  3. power_attr(wake_unlock);  
  4. #endif   
default n
Allow user space to create, activate and deactivate wakeup source
objects with the help of a sysfs-based interface.
宏展开,等价于:
[cpp] view plaincopy技术分享技术分享
 
 
  1. static struct kobj_attribute wake_lock_attr = {   
  2.     .attr   = {               
  3.         .name = “wake_lock”,      
  4.         .mode = 0644,             
  5.     },                    
  6.     .show   = wake_lock_show,             
  7.     .store  = wake_lock_store,        
  8. }  
[cpp] view plaincopy技术分享技术分享
 
 
  1. static struct kobj_attribute wake_unlock_attr = {     
  2.     .attr   = {               
  3.         .name = “wake_unlock”,    
  4.         .mode = 0644,             
  5.     },                    
  6.     .show   = wake_unlock_show,           
  7.     .store  = wake_unlock_store,          
  8. }  
show和store函数的源码位于kernel/power/userwakelock.c。
[cpp] view plaincopy技术分享技术分享
 
 
  1. static struct attribute * g[] = {  
  2.     &state_attr.attr,  
  3. #ifdef CONFIG_PM_TRACE  
  4.     &pm_trace_attr.attr,  
  5.     &pm_trace_dev_match_attr.attr,  
  6. #endif  
  7. #ifdef CONFIG_PM_SLEEP  
  8.     &pm_async_attr.attr,  
  9.     &wakeup_count_attr.attr,  
  10. #ifdef CONFIG_USER_WAKELOCK  
  11.     &wake_lock_attr.attr,  
  12.     &wake_unlock_attr.attr,  
  13. #endif  
  14. #ifdef CONFIG_PM_AUTOSLEEP  
  15.     &autosleep_attr.attr,  
  16. #endif  
  17. #ifdef CONFIG_PM_WAKELOCKS  
  18.     &wake_lock_attr.attr,  
  19.     &wake_unlock_attr.attr,  
  20. #endif  
  21. #ifdef CONFIG_PM_DEBUG  
  22.     &pm_test_attr.attr,  
  23. #endif  
  24. #ifdef CONFIG_PM_SLEEP_DEBUG  
  25.     &pm_print_times_attr.attr,  
  26. #endif  
  27. #endif  
  28. #ifdef CONFIG_FREEZER  
  29.     &pm_freeze_timeout_attr.attr,  
  30. #endif  
  31.     NULL,  
  32. };  
[cpp] view plaincopy技术分享技术分享
 
 
  1. static struct attribute_group attr_group = {  
  2.     .attrs = g,  
  3. };  
pm_init()->
error = sysfs_create_group(power_kobj, &attr_group);
好了,我们该回到原来我们产生疑问的地方了这时我们还得关注其中的另一个函数acquire_wake_lock()->initialize_fds()。
[cpp] view plaincopy技术分享技术分享
 
 
  1. initialize_fds(void)  
  2. {  
  3.     // XXX: should be this:  
  4.     //pthread_once(&g_initialized, open_file_descriptors);  
  5.     // XXX: not this:  
  6.     if (g_initialized == 0) {  
  7.         if(open_file_descriptors(NEW_PATHS) < 0)  
  8.             open_file_descriptors(OLD_PATHS);  
  9.         g_initialized = 1;  
  10.     }  
  11. }  

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

[cpp] view plaincopy技术分享技术分享
 
 
  1. static int  
  2. open_file_descriptors(const char * const paths[])  
  3. {  
  4.     int i;  
  5.     for (i=0; i<OUR_FD_COUNT; i++) {  
  6.         int fd = open(paths[i], O_RDWR);  
  7.         if (fd < 0) {  
  8.             fprintf(stderr, "fatal error opening \"%s\"\n", paths[i]);  
  9.             g_error = errno;  
  10.             return -1;  
  11.         }  
  12.         g_fds[i] = fd;  
  13.     }  
  14.   
  15.     g_error = 0;  
  16.     return 0;  
  17. }  

 

[cpp] view plaincopy
 
 
  1. const char * const NEW_PATHS[] = {  
  2.     "/sys/power/wake_lock",  
  3.     "/sys/power/wake_unlock",  
  4. };  

 

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

 

 

[cpp] view plaincopy
 
 
  1. ssize_t wake_lock_store(  
  2.     struct kobject *kobj, struct kobj_attribute *attr,  
  3.     const char *buf, size_t n)  
  4. {  
  5.     long timeout;  
  6.     struct user_wake_lock *l;  
  7.   
  8.     mutex_lock(&tree_lock);  
  9.     l = lookup_wake_lock_name(buf, 1, &timeout);  
  10.     if (IS_ERR(l)) {  
  11.         n = PTR_ERR(l);  
  12.         goto bad_name;  
  13.     }  
  14.   
  15.     if (debug_mask & DEBUG_ACCESS)  
  16.         pr_info("wake_lock_store: %s, timeout %ld\n", l->name, timeout);  
  17.   
  18.     if (timeout)  
  19.         wake_lock_timeout(&l->wake_lock, timeout);  
  20.     else  
  21.         wake_lock(&l->wake_lock);  
  22. bad_name:  
  23.     mutex_unlock(&tree_lock);  
  24.     return n;  
  25. }  
[cpp] view plaincopy
 
 
  1. struct rb_root user_wake_locks;  
  2. static struct user_wake_lock *lookup_wake_lock_name(  
  3.     const char *buf, int allocate, long *timeoutptr)  
  4. {  
  5.     struct rb_node **p = &user_wake_locks.rb_node;  
  6.     struct rb_node *parent = NULL;  
  7.     struct user_wake_lock *l;  
  8.     int diff;  
  9.     u64 timeout;  
  10.     int name_len;  
  11.     const char *arg;  
  12.   
  13.     /* Find length of lock name and start of optional timeout string */  
  14.     arg = buf;  
  15.     while (*arg && !isspace(*arg))  
  16.         arg++;  
  17. //lock name的长度  
  18.     name_len = arg - buf;  
  19.     if (!name_len)  
  20.         goto bad_arg;  
  21.     while (isspace(*arg))  
  22.         arg++;  
  23.   
  24.     /* Process timeout string */  
  25.     if (timeoutptr && *arg) {  
  26. //(char **)&arg存储的是解析string的结束字符  
  27.         timeout = simple_strtoull(arg, (char **)&arg, 0);  
  28.         while (isspace(*arg))  
  29.             arg++;  
  30. //如果解析string的结束字符不是’\0’  
  31.         if (*arg)  
  32.             goto bad_arg;  
  33.         /* convert timeout from nanoseconds to jiffies > 0 */  
  34.         timeout += (NSEC_PER_SEC / HZ) - 1;  
  35. //do_div(a,b)的返回值是余数,商保存到a中  
  36.         do_div(timeout, (NSEC_PER_SEC / HZ));  
  37.         if (timeout <= 0)  
  38.             timeout = 1;  
  39.         *timeoutptr = timeout;  
  40.     } else if (*arg)  
  41. //timeoutptr为NULL  
  42.         goto bad_arg;  
  43.     else if (timeoutptr)  
  44. //*arg为0,没有timeout  
  45.         *timeoutptr = 0;  
  46.   
  47.     /* Lookup wake lock in rbtree */  
  48. //对于一颗空的红黑树,略过while。wake lock按照name从小到大的顺序存储到user_wake_locks红黑树中  
  49.     while (*p) {  
  50.         parent = *p;  
  51.         l = rb_entry(parent, struct user_wake_lock, node);  
  52.         diff = strncmp(buf, l->name, name_len);  
  53. //如果buf是l->name的子串,那么l->name[name_len]就不会为0,但是buf[name_len]会为0  
  54.         if (!diff && l->name[name_len])  
  55.             diff = -1;  
  56.         if (debug_mask & DEBUG_ERROR)  
  57.             pr_info("lookup_wake_lock_name: compare %.*s %s %d\n",  
  58.                 name_len, buf, l->name, diff);  
  59.   
  60.         if (diff < 0)  
  61.             p = &(*p)->rb_left;  
  62.         else if (diff > 0)  
  63.             p = &(*p)->rb_right;  
  64.         else  
  65.             return l;  
  66.     }  
  67.   
  68.     /* Allocate and add new wakelock to rbtree */  
  69. //allocate为0,表示不需要分配新的wakelock,只在rbtree上查找,找不到就出错了  
  70.     if (!allocate) {  
  71.         if (debug_mask & DEBUG_ERROR)  
  72.             pr_info("lookup_wake_lock_name: %.*s not found\n",  
  73.                 name_len, buf);  
  74.         return ERR_PTR(-EINVAL);  
  75.     }  
  76.     l = kzalloc(sizeof(*l) + name_len + 1, GFP_KERNEL);  
  77.     if (l == NULL) {  
  78.         if (debug_mask & DEBUG_FAILURE)  
  79.             pr_err("lookup_wake_lock_name: failed to allocate "  
  80.                 "memory for %.*s\n", name_len, buf);  
  81.         return ERR_PTR(-ENOMEM);  
  82.     }  
  83.     memcpy(l->name, buf, name_len);  
  84.     if (debug_mask & DEBUG_NEW)  
  85.         pr_info("lookup_wake_lock_name: new wake lock %s\n", l->name);  
  86.     wake_lock_init(&l->wake_lock, WAKE_LOCK_SUSPEND, l->name);  
  87. //插入结点,并染成红色  
  88.     rb_link_node(&l->node, parent, p);  
  89.     rb_insert_color(&l->node, &user_wake_locks);  
  90.     return l;  
  91.   
  92. bad_arg:  
  93.     if (debug_mask & DEBUG_ERROR)  
  94.         pr_info("lookup_wake_lock_name: wake lock, %.*s, bad arg, %s\n",  
  95.             name_len, buf, arg);  
  96.     return ERR_PTR(-EINVAL);  
  97. }  

 

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 plaincopy
 
 
  1. static void wake_lock_internal(  
  2.     struct wake_lock *lock, long timeout, int has_timeout)  
  3. {  
  4.  int type;  
  5.    unsigned long irqflags;  
  6.  long expire_in;  
  7.   
  8.  spin_lock_irqsave(&list_lock, irqflags);  
  9.     type = lock->flags & WAKE_LOCK_TYPE_MASK;  
  10. //检查type是否合法  
  11.     BUG_ON(type >= WAKE_LOCK_TYPE_COUNT);  
  12. //检查是否初始化过  
  13.   BUG_ON(!(lock->flags & WAKE_LOCK_INITIALIZED));  
  14. #ifdef CONFIG_WAKELOCK_STAT  
  15.    if (type == WAKE_LOCK_SUSPEND && wait_for_wakeup) {  
  16.      if (debug_mask & DEBUG_WAKEUP)  
  17.           pr_info("wakeup wake lock: %s\n", lock->name);  
  18.        wait_for_wakeup = 0;  
  19.         lock->stat.wakeup_count++;  
  20.    }  
  21.    if ((lock->flags & WAKE_LOCK_AUTO_EXPIRE) &&  
  22.      (long)(lock->expires - jiffies) <= 0) {  
  23.        wake_unlock_stat_locked(lock, 0);  
  24.        lock->stat.last_time = ktime_get();  
  25.   }  
  26. #endif  
  27.  if (!(lock->flags & WAKE_LOCK_ACTIVE)) {  
  28.      lock->flags |= WAKE_LOCK_ACTIVE;  
  29. #ifdef CONFIG_WAKELOCK_STAT  
  30.       lock->stat.last_time = ktime_get();  
  31. #endif  
  32.     }  
  33. //从inactive_locks上删除  
  34.    list_del(&lock->link);  
  35.    if (has_timeout) {  
  36.       if (debug_mask & DEBUG_WAKE_LOCK)  
  37.            pr_info("wake_lock: %s, type %d, timeout %ld.%03lu\n",  
  38.               lock->name, type, timeout / HZ,  
  39.               (timeout % HZ) * MSEC_PER_SEC / HZ);  
  40.         lock->expires = jiffies + timeout;  
  41.        lock->flags |= WAKE_LOCK_AUTO_EXPIRE;  
  42.         list_add_tail(&lock->link, &active_wake_locks[type]);  
  43.     } else {  
  44.         if (debug_mask & DEBUG_WAKE_LOCK)  
  45.            pr_info("wake_lock: %s, type %d\n", lock->name, type);  
  46.        lock->expires = LONG_MAX;  
  47.         lock->flags &= ~WAKE_LOCK_AUTO_EXPIRE;  
  48.        list_add(&lock->link, &active_wake_locks[type]);  
  49.  }  
  50.    if (type == WAKE_LOCK_SUSPEND) {  
  51.         current_event_num++;  
  52. #ifdef CONFIG_WAKELOCK_STAT  
  53.      if (lock == &main_wake_lock)  
  54.             update_sleep_wait_stats_locked(1);  
  55.       else if (!wake_lock_active(&main_wake_lock))  
  56.             update_sleep_wait_stats_locked(0);  
  57. #endif  
  58.         if (has_timeout)  
  59.             expire_in = has_wake_lock_locked(type);  
  60.      else  
  61.             expire_in = -1;  
  62.      if (expire_in > 0) {  
  63.          if (debug_mask & DEBUG_EXPIRE)  
  64.               pr_info("wake_lock: %s, start expire timer, "  
  65.                    "%ld\n", lock->name, expire_in);  
  66.          mod_timer(&expire_timer, jiffies + expire_in);  
  67.       } else {  
  68.             if (del_timer(&expire_timer))  
  69.                if (debug_mask & DEBUG_EXPIRE)  
  70.                   pr_info("wake_lock: %s, stop expire timer\n",  
  71.                        lock->name);  
  72.          if (expire_in == 0)  
  73.              queue_work(suspend_work_queue, &suspend_work);  
  74.       }  
  75.    }  
  76.    spin_unlock_irqrestore(&list_lock, irqflags);  
  77. }  

第二部分:系统进入睡眠

假如现在我们按了PAD上的power睡眠键,经过一些列的事件处理后,它会调用到PowerManager类中的
[cpp] view plaincopy
 
 
  1. public void goToSleep(long time) {  
  2.     try {  
  3.         mService.goToSleep(time, GO_TO_SLEEP_REASON_USER);  
  4.     } catch (RemoteException e) {  
  5.     }  
  6. }  
而该函数会调用到PowerManagerService类中的public void goToSleep()方法;
[cpp] view plaincopy
 
 
  1. @Override // Binder call  
  2. public void goToSleep(long eventTime, int reason) {  
  3.     if (eventTime > SystemClock.uptimeMillis()) {  
  4.         throw new IllegalArgumentException("event time must not be in the future");  
  5.     }  
  6.   
  7.     mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);  
  8.   
  9.     final long ident = Binder.clearCallingIdentity();  
  10.     try {  
  11.         goToSleepInternal(eventTime, reason);  
  12.     } finally {  
  13.         Binder.restoreCallingIdentity(ident);  
  14.     }  
  15. }  
[cpp] view plaincopy
 
 
  1. private void goToSleepInternal(long eventTime, int reason) {  
  2.     synchronized (mLock) {  
  3.         if (goToSleepNoUpdateLocked(eventTime, reason)) {  
  4.             updatePowerStateLocked();  
  5.         }  
  6.     }  
  7. }  
goToSleepNoUpdateLocked是goToSleep功能的计算者,来决定是否要休眠,而updatePowerStateLocked函数算是功能的执行者,而且这个执行者同时负责执行了很多其他的功能。其实goToSleepNoUpdateLocked并没有真正地让device进行sleep,仅仅只是把PowerManagerService中一些必要的属性进行了赋值,等会在分析updatePowerStateLocked的时候,再给出解释。在PowerManagerService的代码中,有很多的方法的名字中都含有xxxNoUpdateLocked这样的后缀,我觉得这样做大概是因为,都类似于goToSleepNoUpdateLocked方法,并没有真正地执行方法名字所描述的功能,仅仅是更新了一些必要的属性。 所以在Android系统中可以把多个power state属性的多个变化放在一起共同执行的,而真正的功能执行者就是updatePowerStateLocked。
[cpp] view plaincopy
 
 
  1. private void updatePowerStateLocked() {  
  2.        if (!mSystemReady || mDirty == 0) {//如果系统没有准备好,或者power state没有发生任何变化,这个方法可以不用执行的  
  3.            return;  
  4.        }  
  5.   
  6.   if(!SystemProperties.getBoolean("ro.platform.has.mbxuimode", false)) {  
  7.            if (isHdmiPlugged()) {  
  8.                return;  
  9.            }  
  10.    }  
  11.        // Phase 0: Basic state updates.  
  12.        updateIsPoweredLocked(mDirty);  
  13.        updateStayOnLocked(mDirty);  
  14.   
  15.        // Phase 1: Update wakefulness.  
  16.        // Loop because the wake lock and user activity computations are influenced  
  17.        // by changes in wakefulness.  
  18.        final long now = SystemClock.uptimeMillis();  
  19.        int dirtyPhase2 = 0;  
  20.        for (;;) {  
  21.            int dirtyPhase1 = mDirty;  
  22.            dirtyPhase2 |= dirtyPhase1;  
  23.            mDirty = 0;  
  24.   
  25.            updateWakeLockSummaryLocked(dirtyPhase1);  
  26.            updateUserActivitySummaryLocked(now, dirtyPhase1);  
  27.            if (!updateWakefulnessLocked(dirtyPhase1)) {  
  28.                break;  
  29.            }  
  30.        }  
  31.   
  32.        // Phase 2: Update dreams and display power state.  
  33.        updateDreamLocked(dirtyPhase2);  
  34.        updateDisplayPowerStateLocked(dirtyPhase2);  
  35.   
  36.        // Phase 3: Send notifications, if needed.  
  37.        if (mDisplayReady) {  
  38.            sendPendingNotificationsLocked();  
  39.        }  
  40.   
  41.        // Phase 4: Update suspend blocker.  
  42.        // Because we might release the last suspend blocker here, we need to make sure  
  43.        // we finished everything else first!  
  44.        updateSuspendBlockerLocked();  
  45.    }  
对sys/power/state进行读写操作的时候,(linux/kernel/power/main.c)中的state_store()函数会被调用,在该函数中会分成两个分支:
Android特有的earlysuspend: request_suspend_state(state)
Linux标准的suspend: enter_state(state)
 
0

Android休眠唤醒机制简介(二)

标签:row   not   分配   nat   系统调用   blog   lag   流程   access   

原文地址:http://www.cnblogs.com/zzb-Dream-90Time/p/7650226.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!