Android智能手机或机顶盒子为了进入省电模式、所以就需要有待机功能。

PowerManager.java 类提供了如下的电源管理功能

public void goToSleep(long time) 强迫设备进入睡眠状态

public void reboot(String reason)  重启设备

提供了内部类: public final class WakeLock

public void acquire(long timeout) 申请待机锁

public void release(int flags)  释放待机锁

我这里讲的主要是:

利用Linux内核原有的睡眠唤醒模块上基础上,在Android系统上主要增加了下面三个机制:

• Wake Lock 唤醒锁机制;
     • Early Suspend 预挂起机制;
     • Late Resume 迟唤醒机制;

基本原理:

当启动一个应用程序的时候,它可以申请一个wake_lock唤醒锁,每当申请成功之后都会在内核中注册一下(通知系统内核,现在已经有锁被申请,系统内核的wake_lock_store把它加入红黑树中),当应用程序在某种情况下释放wake_lock的时候,会注销之前所申请的wake_lock。特别要注意的是:只要是系统中有一个wake_lock的时候,系统此时都不能进行睡眠。但此时各个模块可以进行early_suspend。当系统中所有的wake_lock都被释放之后,系统就会进入真正的kernel的睡眠状态。在系统启动的时候会创建一个主唤醒锁main_wake_lock,该锁是内核初始化并持有的一个WAKE_LOCK_SUSPEND属性的非限时唤醒锁。因此,系统正常工作时,将始终因为该锁被内核持有而无法进入睡眠状态。也就是说在不添加新锁的情况下,只需将main_wake_lock 解锁,系统即可进入睡眠状态。

先看一下整体流程层次结构图:

下面按照层次结构从java层分析:

frameworks/base/core/java/android/os/PowerManager.java

@public final class WakeLock  内部类

获取待机锁:

public void acquire() {synchronized (mToken) {acquireLocked();}}private void acquireLocked() {if (!mRefCounted || mCount++ == 0) {// Do this even if the wake lock is already thought to be held (mHeld == true)// because non-reference counted wake locks are not always properly released.// For example, the keyguard's wake lock might be forcibly released by the// power manager without the keyguard knowing.  A subsequent call to acquire// should immediately acquire the wake lock once again despite never having// been explicitly released by the keyguard.mHandler.removeCallbacks(mReleaser);try {mService.acquireWakeLock(mToken, mFlags, mTag, mWorkSource);} catch (RemoteException e) {}mHeld = true;}}

以上代码很清楚,判定标志mRefCounted 为false 或mCount 值为0即可进入获取待机锁、并将mCount加1

此时调用 mService.acquireWakeLock(mToken, mFlags, mTag, mWorkSource);

mService 就是 PowerManagerService 类

frameworks/base/services/java/com/android/server/PowerManagerService.java

@acquireWakeLock -> acquireWakeLockInternal ->updatePowerStateLocked

重要的操作都在这里做的,五个步骤

private void updatePowerStateLocked() {if (!mSystemReady || mDirty == 0) {return;}// Phase 0: Basic state updates.updateIsPoweredLocked(mDirty);updateStayOnLocked(mDirty);// Phase 1: Update wakefulness.// Loop because the wake lock and user activity computations are influenced// by changes in wakefulness.final long now = SystemClock.uptimeMillis();int dirtyPhase2 = 0;for (;;) {int dirtyPhase1 = mDirty;dirtyPhase2 |= dirtyPhase1;mDirty = 0;updateWakeLockSummaryLocked(dirtyPhase1);updateUserActivitySummaryLocked(now, dirtyPhase1);if (!updateWakefulnessLocked(dirtyPhase1)) {break;}}// Phase 2: Update dreams and display power state.updateDreamLocked(dirtyPhase2);updateDisplayPowerStateLocked(dirtyPhase2);// Phase 3: Send notifications, if needed.if (mDisplayReady) {sendPendingNotificationsLocked();}// Phase 4: Update suspend blocker.// Because we might release the last suspend blocker here, we need to make sure// we finished everything else first!updateSuspendBlockerLocked();}

最后一个方法 updateSuspendBlockerLocked() 将会调用native方法

@mWakeLockSuspendBlocker.acquire(); -> nativeAcquireSuspendBlocker

private static native void nativeAcquireSuspendBlocker(String name);

此时将进入jni 层:

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());}

实现相当简单、不解释了。

hardware/libhardware_legacy/power/power.c

int acquire_wake_lock(int lock, const char* id){initialize_fds(); // 打开句柄 open("/sys/power/wake_lock")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)); // 写入命令
}

此时将进入内核代码分析是如何做的。

kernel/power/main.c - PM subsystem core functionality.

static ssize_t wake_lock_store(struct kobject *kobj,struct kobj_attribute *attr,const char *buf, size_t n)
{int error = pm_wake_lock(buf);return error ? error : n;
}

kernel/power/wakelock.c

int pm_wake_lock(const char *buf)
{const char *str = buf;struct wakelock *wl;u64 timeout_ns = 0;size_t len;int ret = 0;while (*str && !isspace(*str))str++;len = str - buf;if (!len)return -EINVAL;if (*str && *str != '\n') {/* Find out if there's a valid timeout string appended. */ret = kstrtou64(skip_spaces(str), 10, &timeout_ns);if (ret)return -EINVAL;}mutex_lock(&wakelocks_lock);wl = wakelock_lookup_add(buf, len, true);if (IS_ERR(wl)) {ret = PTR_ERR(wl);goto out;}if (timeout_ns) {u64 timeout_ms = timeout_ns + NSEC_PER_MSEC - 1;do_div(timeout_ms, NSEC_PER_MSEC);__pm_wakeup_event(&wl->ws, timeout_ms);} else {__pm_stay_awake(&wl->ws);}wakelocks_lru_most_recent(wl);out:mutex_unlock(&wakelocks_lock);return ret;
}

这块没有细看、有兴趣的朋友可以看看。本质就是利用红黑树查看锁的情况,最后该函数首先sync文件系统,然后调用pm_suspend(request_suspend_state),接下来pm_suspend()就会调用 enter_state()来进入 linux的suspend流程。

机顶盒的资源也可以实现待机函数、这样子即可快速进入待机模式。

释放待机锁的流程与获取待机锁差不多就不多说了。

最后说明一下:

WakeLock 类型以及说明:

PARTIAL_WAKE_LOCK:保持CPU 运转,屏幕和键盘灯有可能是关闭的。
    SCREEN_DIM_WAKE_LOCK:保持CPU 运转,允许保持屏幕显示但有可能是灰的,允许关闭键盘灯
    SCREEN_BRIGHT_WAKE_LOCK:保持CPU 运转,允许保持屏幕高亮显示,允许关闭键盘灯
    FULL_WAKE_LOCK:保持CPU 运转,保持屏幕高亮显示,键盘灯也保持亮度
    ACQUIRE_CAUSES_WAKEUP:强制使屏幕亮起,这种锁主要针对一些必须通知用户的操作.
    ON_AFTER_RELEASE:当锁被释放时,保持屏幕亮起一段时间

最后 AndroidManifest.xml 声明权限:
    <uses-permission android:name="android.permission.WAKE_LOCK"/>
    <uses-permission android:name="android.permission.DEVICE_POWER"/>

应用程序中如果要在待机前保存数据状态的话,要保证此过程中不会进入待机。可以在 onResume() 或者 onStart() 中申请 wakelock 锁,即调用acquireWakeLock()方法。

在 onPause() 或者 onDistroy() 中处理应用待机后再释放掉 wakelock 锁,此时调用releaseWakeLock()方法

最后一点需要注意下:

另外WakeLock的设置是 Activiy 级别的,不是针对整个Application应用的。所以application下有多个activity一定需要注意下!

Android 待机功能流程分析相关推荐

  1. Android SDCard UnMounted 流程分析(三)

    前篇地址 Android SDCard UnMounted 流程分析(一) Android SDCard UnMounted 流程分析(二) 前一篇讲到SDCard unmout onEvent 发送 ...

  2. android camera2 API流程分析

    Android camera2 API流程分析 Android5.0之后,新推出来了一个类,android.hardware.camera2,与原来的camera的类实现照相和拍视频的流程有所不同,原 ...

  3. Android UI绘制流程分析(三)measure

    源码版本Android 6.0 请参阅:http://androidxref.com/6.0.1_r10 本文目的是分析从Activity启动到走完绘制流程并显示在界面上的过程,在源码展示阶段为了使跟 ...

  4. Android -- Wifi启动流程分析

    Android -- Wifi启动流程分析 Android网络各个模式中,Wifi应该是目前最常用的一种网络方式了:下面就简单介绍下Android中Wifi的启动流程. 当我在Setting菜单里点击 ...

  5. 【SemiDrive源码分析】【X9芯片启动流程】27 - AP1 Android Preloader启动流程分析(加载atf、tos、bootloader镜像后进入BL31环境)

    [SemiDrive源码分析][X9芯片启动流程]27 - AP1 Android Preloader启动流程分析(加载atf.tos.bootloader镜像后进入BL31环境) 一.Android ...

  6. android volume挂载流程,Android SDCard UnMounted 流程分析(一)

    Android SDCard框架 Android SDCard框架,我们修改一般涉及到四大模块 Linux Kernel 用于检测热拔插,作为框架开发者来说,这者不用涉及 Vold 作为Kernel ...

  7. Android流媒体处理流程分析

    文章目录 1. WiFiDisplay简介 2.RTSP协议流程分析 3. 流媒体协议简介 4. RTP.RTCP协议简介 4.1 RTP协议 4.1 RTP载荷H264码流 4.2 RTP载荷PS码 ...

  8. android app启动流程分析,Android应用开发之Android 7.0 Launcher3的启动和加载流程分析...

    本文将带你了解Android应用开发Android 7.0 Launcher3的启动和加载流程分析,希望本文对大家学Android有所帮助. Android 7.0 Launcher3的启动和加载流程 ...

  9. Android SDCard Mount 流程分析(一)

    点击打开链接 前段时间对Android 的SDCard unmount 流程进行了几篇简短的分析,由于当时只是纸上谈兵,没有实际上的跟进,可能会有一些误导人或者小错误.今天重新梳理了头绪,针对moun ...

最新文章

  1. Fork and Join: Java Can Excel at Painless Parallel Programming Too!---转
  2. Google 出品的 Java 编码规范,权威又科学,强烈推荐
  3. mysql中find_in_set()函数的使用
  4. Spring之AOP由浅入深
  5. js 实现“倒计时” 以及 N秒后跳转页面
  6. 最全面实用的MySql操作大全。
  7. 邓侃:深度强化学习“深”在哪里?
  8. windowskb2685811补丁_KB898461补丁
  9. Python使用技巧
  10. Python TypeError: object() takes no parameters
  11. cefsharp异步抓取html5,winform插件cefsharp65最新版完美demo,完美flash、html5、和调用摄像头支持,部署就能用...
  12. spark学习-70-源代码:Endpoint模型介绍(2)-启动流程
  13. Linux内核深入理解定时器和时间管理(4):定时器 timer
  14. 搜索引擎中用到的一些拆词方式解析
  15. 系统动力学仿真软件Vensim下载
  16. 《码出高效:Java开发手册》百度网盘下载
  17. kiv8测量方法_measure_测量 | measure_Scikit image_参考手册_非常教程
  18. Rust 限流算法crate调研
  19. 《OKR:源于英特尔和谷歌的目标管理利器》读书笔记
  20. CSU 1726-你经历过绝望吗?两次!(BFS+剪枝)

热门文章

  1. 打印日期(华中科技大学考研机试)
  2. 微信企业号信息接收服务器,微信企业号拟部署HTTPS协议,移步到微:早已升级...
  3. 诱骗芯片HUSB238A:USB PD3.1 EPR助力24V直流电机驱动
  4. Failed to execute goal org.codehaus.mojo:exec-maven-plugin:1.6.0
  5. JavaEye被封杀,求真想
  6. 【广州市青年科技工作者协会主办 | 青年论坛 | 往届均已见刊检索 | 稳定EI 】
  7. Escaping closure captures non-escaping parameter 'xx'
  8. Matlab灰度图像反转,对数变换,幂次变换
  9. [原创]大部调整的IT遐想
  10. 我从研究院转型为头部互联网分析师