Windows CE的电源管理之三

    本篇将以Windows Mobile为例介绍Windows CE电源管理的实现,大体上,Windows Mobile分为Pocket PC和Smartphone两种版本。这两者之间的主要区别在于触摸屏和电源模型,Smartphone采用的是“Always On”模型。为了说清楚它们的区别,我们就先从系统电源状态说起吧(这里有些系统电源状态是从WM5开始才有的)。

1. Windows Mobile的系统电源状态

  • On:用户与系统交互时的状态;
  • BacklightOff:在一段时间内(默认15秒),如果一直没有用户操作(比如按下某个键或者触摸屏幕),就关闭背光,这时其他的设备都没变化。这个timeout值可以通过控制面板进行设置;
  • UserIdle:这个状态只在Smartphone中被使用。经过一段稍长的时间,如果一直没有用户操作,就关闭背光和LCD。这个timeout值可以通过控制面板进行设置;
  • ScreenOff:一般由某些程序指定,才进入这个状态。比如音乐播放器程序,当你听音乐时按下某个键可以将屏幕关闭。PocketPC和Smartphone都使用这个状态,它与UserIdle的不同在于,ScreenOff意味着“用户主动关闭了显示,只有当他按下电源键时才重新显示”,而UserIdle意味着“用户有段时间没操作了,那么我们可以关闭屏幕来省电”,所以在UserIdle时,随便按下Smartphone的哪个键都会启动显示;
  • Suspend:这是PocketPC的睡眠模式,几乎所有设备都被关闭,直到某个硬件设备触发中断才将系统唤醒,这个timeout值可以通过控制面板进行设置(默认为3分钟);
  • Resuming:这是PocketPC被唤醒后的状态,这时屏幕是关闭的,并启动一个15秒的计时器,在这段时间内决定接下来进入哪个状态,如果计时器超时则重新回到睡眠状态;
  • Unattended:这个状态只在PocketPC中被使用,用户对其不会有所察觉。有些程序,如ActiveSync每5分钟会唤醒系统进行同步,同步完成后再让系统继续睡眠,这段时间不希望打扰用户,即程序在后台执行。

    可以通过注册表查看系统电源状态对应的具体设备的电源状态,[HLM\System\CurrentControlSet\Control\Power\State]。

    现在我们知道,Smartphone没有真正的睡眠模式,即使它会在一段时间后关闭背光和屏幕,但它并没有睡着,只是休息一下眼睛罢了,它的大脑和四肢仍在正常工作。PocketPC所采用的模型比Smartphone要复杂的多,你可以按下电源键让系统睡眠,在必要时,也可以唤醒系统做一些工作然后再继续睡眠。如果你在Smartphone上运行一个桌面精灵之类的程序,她为了引起你的注意,长时间的蹦啊跳啊,不管白天还是黑夜,可想而知,你的待机时间将......

    你可能会觉得PocketPC的“Sleep”模型比Smartphone的“Always On”模型要省电,其实恰恰相反。因为在系统睡眠的过程中,它需要通知所有的设备驱动,为了让它们保存一些重要的信息并关闭相应的硬件设备,在系统被唤醒时也需要通知它们恢复先前的工作。这个过程不仅耗时还可能会耗更多的电,因为一些设备在频繁的状态转换过程中会消耗比较多的能量。这也就是为什么当你收到一条短信时,睡眠状态的PocketPC要花3到6秒的时间来处理,而Smartphone只需要几个微秒:)

2. Windows Mobile的电源管理策略

    我们可以用系统电源状态机来简单的描述Windows Mobile的电源管理策略,以PocketPC为例,系统电源状态机如下图所示:

                           FSM

    系统内部的电源管理器负责协调电源状态的转换,电源状态的转换主要由一下几种方式触发:

  • 计时器超时:SuspendTimeout和ResumingSuspendTimeout,分别对应于第一节介绍Suspend和Resuming状态时所提到的计时器。细说起来,它们每个又有两个值,分别对应着电源供电时和电池供电时的超时值,也就是注册表[HLM\System\CurrentControlSet\Control\Power\Timeout]中的ACSuspendTimeout、BattSuspendTimeout、ACResumingSuspendTimeout、BattResumingSuspendTimeout;
  • 系统调用:驱动程序或应用程序通过相应的API,请求进入某种电源状态。这类API在前面的文章中已经有所介绍,如SetSystemPowerState、SetPowerRequirement、DevicePowerNotify等;
  • 平台相关的系统调用:通过PowerPolicyNotify通知电源管理器发生了某个事件,它的实现比较灵活,驱动程序或应用程序可以通过相应的参数与电源管理器进行交互,比如PPN_POWERCHANGE、PPN_SUSPENDKEYPRESSED、PPN_UNATTENDEDMODE等,参见"pmpolicy.h";
  • 直接访问内核对象:事件(Event)作为Windows CE系统的内核对象,可以通过事件名称在进程间共享,因此我们可以访问电源管理器中的两个事件,它们的名字分别是_T("PowerManager/ReloadActivityTimeouts")、_T("PowerManager/SystemIdleTimerReset")。如果你的程序需要动态修改那几个计时器的时间长度,可以通过第一个事件通知电源管理器重新读取注册表中计时器的值,而第二个事件与SystemIdleTimerReset功能一样,可以阻止系统进入睡眠状态。

3. Windows Mobile电源管理相关API的应用

    最后,通过几个应用场景简单介绍一下常用的电源管理相关的API的使用:

  • 如果你在设计的是媒体播放器程序,不希望在播放电影时,系统自动转入Suspend状态,这时可以每隔30秒调用一次SystemIdleTimerReset,它会帮你重置那个计时器;如果你还想同时保持背光,那么可以调用SetPowerRequirement(TEXT("BKL1:"), D0, POWER_NAME, NULL, 0);如果你提供一个按钮允许用户关闭屏幕,那么调用SetSystemPowerState(NULL, POWER_STATE_IDLE, 0);
  • 如果你在设计的是天气预报程序,需要每天早上6点在线更新天气信息,这时可以调用CeRunAppAtTime,系统到时会被RTC中断唤醒,还记得前面提到的那个15秒的计时器吗,这时你的程序应该在15秒内请求进入Unattended状态,否则系统将重新回到睡眠状态。在处理更新的过程中,还是应该每隔30秒调用一次SystemIdleTimerReset,在处理完更新后,应该再次调用CeRunAppAtTime,并放弃Unattended状态。请注意,在电源管理器的实现代码中,用了一个引用计数的变量(gdwUnattendedModeRequests)统计所有对Unattended状态的请求,所以PowerPolicyNotify(PPN_UNATTENDEDMODE, TRUE);和PowerPolicyNotify(PPN_UNATTENDEDMODE, FALSE);要成对出现,否则系统将无法回到睡眠状态。
  • 如果你要开发一个监控电池状态的程序,首先应该创建一个接收状态通知的线程,在这个线程里调用RequestPowerNotifications,这个函数的第一个参数是一个消息队列的句柄,所以必须先创建一个消息队列(CreateMsgQueue),第二个参数是你希望得到的通知类型,这里要用到的是PBT_POWERSTATUSCHANGE|PBT_POWERINFOCHANGE,然后线程就可以等待通知了(WaitForSingleObject),一旦有通知到来,线程通过ReadMsgQueue读取消息的内容,再做些更新UI的工作。
    相关示例代码
    //***************************************************************************
    // Function Name: PowerNotificationThread
    //
    // Purpose: listens for power change notifications
    //
    DWORD PowerNotificationThread(LPVOID pVoid)
    {
       
    // size of a POWER_BROADCAST message
        DWORD cbPowerMsgSize = sizeof POWER_BROADCAST + (MAX_PATH * sizeof TCHAR);

       
    // Initialize our MSGQUEUEOPTIONS structure
        MSGQUEUEOPTIONS mqo;
        mqo.dwSize
    = sizeof(MSGQUEUEOPTIONS);
        mqo.dwFlags
    = MSGQUEUE_NOPRECOMMIT;
        mqo.dwMaxMessages
    = 4;
        mqo.cbMaxMessage
    = cbPowerMsgSize;
        mqo.bReadAccess
    = TRUE;             
                                            
       
    // Create a message queue to receive power notifications
        HANDLE hPowerMsgQ = CreateMsgQueue(NULL, &mqo);
       
    if (NULL == hPowerMsgQ)
       
    {
            RETAILMSG(
    1, (L"CreateMsgQueue failed: %x\n", GetLastError()));
           
    goto Error;
        }


       
    // Request power notifications
        HANDLE hPowerNotifications = RequestPowerNotifications(hPowerMsgQ, PBT_POWERSTATUSCHANGE | PBT_POWERINFOCHANGE);
       
       
    if (NULL == hPowerNotifications)
       
    {
            RETAILMSG(
    1, (L"RequestPowerNotifications failed: %x\n", GetLastError()));
           
    goto Error;
        }


        HANDLE rgHandles[
    2] = {0};
        rgHandles[
    0] = hPowerMsgQ;
        rgHandles[
    1] = g_hEventShutDown;

       
    // Wait for a power notification or for the app to exit
        while(WaitForMultipleObjects(2, rgHandles, FALSE, INFINITE) == WAIT_OBJECT_0)
       
    {
            DWORD cbRead;
            DWORD dwFlags;
            POWER_BROADCAST
    *ppb = (POWER_BROADCAST*) new BYTE[cbPowerMsgSize];
               
           
    // loop through in case there is more than 1 msg
            while(ReadMsgQueue(hPowerMsgQ, ppb, cbPowerMsgSize, &cbRead,
                              
    0, &dwFlags))
           
    {
               
    switch (ppb->Message)
               
    {
                   
    case PBT_POWERINFOCHANGE:
                   
    {
                        RETAILMSG(
    1,(L"Power Notification Message: PBT_POWERINFOCHANGE\n"));

                       
    // PBT_POWERINFOCHANGE message embeds a
                       
    // POWER_BROADCAST_POWER_INFO structure into the
                       
    // SystemPowerState field
                        PPOWER_BROADCAST_POWER_INFO ppbpi =
                            (PPOWER_BROADCAST_POWER_INFO) ppb
    ->SystemPowerState;
                       
    if (ppbpi)
                       
    {
                            RETAILMSG(
    1,(L"Length: %d", ppb->Length));
                            RETAILMSG(
    1,(L"BatteryLifeTime = %d\n",ppbpi->dwBatteryLifeTime));
                            RETAILMSG(
    1,(L"BatterFullLifeTime = %d\n",
                                         ppbpi
    ->dwBatteryFullLifeTime));
                            RETAILMSG(
    1,(L"BackupBatteryLifeTime = %d\n",
                                         ppbpi
    ->dwBackupBatteryLifeTime));
                            RETAILMSG(
    1,(L"BackupBatteryFullLifeTime = %d\n",
                                         ppbpi
    ->dwBackupBatteryFullLifeTime));
                            RETAILMSG(
    1,(L"ACLineStatus = %d\n",ppbpi->bACLineStatus));
                            RETAILMSG(
    1,(L"BatteryFlag = %d\n",ppbpi->bBatteryFlag));
                            RETAILMSG(
    1,(L"BatteryLifePercent = %d\n",
                                         ppbpi
    ->bBatteryLifePercent));
                            RETAILMSG(
    1,(L"BackupBatteryFlag = %d\n",
                                         ppbpi
    ->bBackupBatteryFlag));
                            RETAILMSG(
    1,(L"BackupBatteryLifePercent = %d\n",
                                         ppbpi
    ->bBackupBatteryLifePercent));
                        }

                       
    break;
                    }


                   
    default:
                       
    break;
                }


                UpdateUI();
            }


            delete[] ppb;
        }


    Error:
       
    if (hPowerNotifications)
            StopPowerNotifications(hPowerNotifications);

       
    if (hPowerMsgQ)
            CloseMsgQueue(hPowerMsgQ);

       
    return NULL;
    }

 

* 原创文章,转载请注明出处

转载于:https://www.cnblogs.com/jasonye/archive/2008/03/06/1094213.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/299827.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

跟你们讲一个鬼故事,TA回来了!

全世界只有3.14 % 的人关注了青少年数学之旅真正决定人与人之间的差距的,其实是我们对事物的见识与内心的格局,见识的深浅决定人生的深浅,格局的大小决定了人生之路是宽是窄。今天给大家推荐几个有深度、有想法的公众号,希望能够给…

java之static关键词的作用

static关键词的作用 1、静态成员变量的语法特定 2、静态函数的语法特定 3、静态代码块的语法特定 定义静态成员变量 Person.java class Person{ static int a; }按照以前可以这么调用 public class Test1{ public static void main(String[] args){ Person person new Per…

分布式事务最终一致性-CAP框架轻松搞定

前言对于分布式事务,常用的解决方案根据一致性的程度可以进行如下划分:强一致性(2PC、3PC):数据库层面的实现,通过锁定资源,牺牲可用性,保证数据的强一致性,效率相对比较低。弱一致性(TCC)&…

Cus系统beta1.2发布

2019独角兽企业重金招聘Python工程师标准>>> 经过小伙伴的努力,Cus后台管理系统开发完成,完善了后台系统,权限控制,新闻发布,商务合作等等功能 主要功能包括: 后台系统截图 更多后台系统截图请点…

区区6位密码,凭什么守护我的百万家产?

全世界只有3.14 % 的人关注了青少年数学之旅今天超模君非常的开心你问为什么?当然是——又双叒可以买新的数学书好开心!不过在这欢快的气氛中超模君却听见了小天的叹气声玩笑归玩笑但是银行的密码系统真很安全的吗?今天我们就来讨论下密码学的…

Java开发之上班摸鱼!写最少的代码!

I 前言 本次分享一下我所知道的如何写最少的代码的小技巧,如果你有更好的方案,欢迎在评论区留言,方案很棒的话,加我交流圈,为你送上冬天的一杯奶茶~ Java:我想返回多个返回值 秀一下Go的多返回值&#xf…

Windows 11 预览版 Build 22000.120 发布

微软现已发布第五个 Windows 11 预览版更新 KB5005188,版本号升级至 Build 22000.120。本次更新面向 Dev 频道和 Beta 频道的 Windows 预览体验成员推出。Windows 11 Insider Preview Build 22000.120 主要变化如下:1.全新的 Family Safety(家…

robocopy帮助

一 Robocopy简介 Robocopy 是一个功能超强的32位的文件复制工具,该工具来自windows资源包,可以直接在网上下载。 使用Robocopy你能够拷贝单个目录,或迭代的拷贝目录及其所有的子目录。该工具通过文件是否存在于源目录,目标目录&am…

有趣的灵魂连墓碑都很酷! | 今日趣图

全世界只有3.14 % 的人关注了青少年数学之旅(图源别是个沙雕吧,侵权删)

实施Exchange 2013中的 MailTip

实施Exchange 2013中的 MailTip邮件提示是用户撰写邮件时向其显示的提示性消息。Microsoft Exchange Server 2013 将分析邮件(包括向其发送了邮件的收件人的列表),如果检测到潜在问题,它将使用邮件提示在邮件发送之前通知用户。借…

防弹玻璃为啥会被钢球砸碎?这就是一道高中物理题!

全世界只有3.14 % 的人关注了青少年数学之旅马斯克,硅谷钢铁侠,全世界最具煽动力的企业家。旗下公司特斯拉最新电动皮卡,一经亮相就欢呼一片,传播到炸,看起来又要重新定义一个品类。然而也有网友“提醒”——如今的马斯…

八种ADSL接入情况中断流现象分析

转载自:网盟技术[url]http://technic.txwm.com[/url] 线路不稳定 如果住所离电信局太远(5公里以上)可以向电信部门申报。确保线路连接正确(不同的话音分离器的连接方法有所不同,请务必按照说明书指引正确连接)。同时确保线路通讯质量良好没有被干扰&…

Java之jdk与jre的区别

很多程序员已经干了一段时间java了依然不明白jdk与jre的区别。 JDK就是Java Development Kit.简单的说JDK是面向开发人员使用的SDK,它提供了Java的开发环境和运行环境。SDK是Software Development Kit 一般指软件开发包,可以包括函数库、编译程序等。 …

设计模式之组合

组合模式介绍一棵树结构组合模式是把相似对象或方法组合成一组可被调用的结构树对象的设计思路。组合模式不只是可以运用于规则决策树,还可以做服务包装将不同的接口进行组合配置,对外提供服务能力,减少开发成本。组合模式的主要解决的是一系…

leetcode中的状态机类型的题目

1 总结 一般是涉及到多个状态之间的转换,需要定义一个具有多个枚举值的变量,各个状态之间通过各种条件互相变化 2 LC57. 插入区间 2.1 解析 先是要确定新区间插入到哪一个位置(也有可能),插入后需要确定这个区间是否…

如何用Python进行数据探索,探索竞赛优胜方案?

全世界只有3.14 % 的人关注了 青少年数学之旅 AI这个词相信大家都非常熟悉,近几年来人工智能圈子格外热闹,光是AlphoGo就让大家对它刮目相看。 随着大数据时代信息科技的快速发展,各种各样的数据充斥着我们的生活。而我们又当如何有效利用数据…

联想ThinkPad笔记本广告向苹果MacBook Air开战

联想ThinkPad笔记本广告向苹果MacBook Air开战 [url]http://www.sina.com.cn[/url] 2008年03月24日 07:21 新浪科技联想ThinkPad X300笔记本广告,暗讽苹果MacBook AirMacbook Air最厚的地方仅有1.94cm,边缘仅0.4cm视频:ThinkPad X300对比Mac…

基于 gRPC 和 .NET Core 的服务器流

原文:https://bit.ly/3lpz8Ll作者:Chandan Rauniyar翻译:精致码农-王亮早在 2019 年,我写过《用 Mapbox 绘制位置数据》一文,详细介绍了我如何通过简单的文件上传,用 Mapbox 绘制约 230 万个位置点。本文介…

jQuery入门[2]-选择器[转]

jQuery之所以令人爱不释手&#xff0c;在于其强大的选择器表达式令DOM操作优雅而艺术。jQuery的选择符支持id,tagName,css1-3 expressions,XPath&#xff0c;参见&#xff1a;http://docs.jquery.com/SelectorsDEMO:<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Tran…

是个狠角色。。 | 今日最佳

全世界只有3.14 % 的人关注了青少年数学之旅&#xff08;图源洱海弥&#xff0c;侵权删&#xff09;