zoukankan      html  css  js  c++  java
  • Android休眠唤醒机制简介(二)

    本文转载自: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在CODE上查看代码片派生到我的代码片
     
     
    1. public void acquire() {  
    2.     synchronized (mToken) {  
    3.         acquireLocked();  
    4.     }  
    5. }  
    [cpp] view plaincopy在CODE上查看代码片派生到我的代码片
     
     
    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在CODE上查看代码片派生到我的代码片
     
     
    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在CODE上查看代码片派生到我的代码片
     
     
    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在CODE上查看代码片派生到我的代码片
     
     
    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在CODE上查看代码片派生到我的代码片
     
     
    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在CODE上查看代码片派生到我的代码片
     
     
    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在CODE上查看代码片派生到我的代码片
     
     
    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在CODE上查看代码片派生到我的代码片
     
     
    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' ", 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在CODE上查看代码片派生到我的代码片
     
     
    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在CODE上查看代码片派生到我的代码片
     
     
    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在CODE上查看代码片派生到我的代码片
     
     
    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在CODE上查看代码片派生到我的代码片
     
     
    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在CODE上查看代码片派生到我的代码片
     
     
    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在CODE上查看代码片派生到我的代码片
     
     
    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在CODE上查看代码片派生到我的代码片
     
     
    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在CODE上查看代码片派生到我的代码片
     
     
    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在CODE上查看代码片派生到我的代码片
     
     
    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" ", 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 ", 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的结束字符不是’’  
    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 ",  
    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 ",  
    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 ", 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 ", 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 ",  
    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 ", 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 ",  
    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 ", 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 ", 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 ",  
    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
  • 相关阅读:
    线程总结(1)
    (转)远程线程DEMO
    VCL 中TList源码分析
    MVC Controller向View传值(ViewData与ViewBag)
    ASP.NET MVC 下拉框的传值的两种方式(第二种方式未完成)
    将数据在[Excel]和[任何数据源]之间导入导出_可临时保存查询结果
    服务器控件之二
    关闭窗口动画,加速窗口
    让XP控制台字符编码在UTF8与GBK之间切换
    WCF应用的编码实现
  • 原文地址:https://www.cnblogs.com/zzb-Dream-90Time/p/7650226.html
Copyright © 2011-2022 走看看