Power to the Developers part 2


In Power to the People we learned that it’s very bad for your app to use the CPU unnecessarily.  In Power to the Developers part 1 we learned a few easy ways to make your code stop burning CPU cycles.  Now we’re going to learn a more complicated mechanism for the same thing.  You’ll use this technique if, for various reasons, the previous techniques won’t work for you (a prime example being that you’re writing a home screen plug in).  This entry assumes that you have a basic understanding of Power Manager, which you can get by reading Power to the System.



Wouldn’t it be nice if?
The previous techniques were to not burn CPU cycles (i.e. animate something) if your app wasn’t in the foreground, and to only animate for so long after your app received input.  But what if your code is hosted in some other app and you don’t really know if you’re in the foreground?  And what if you don’t really ever receive input?  Wouldn’t it be nice if there was some component in the system that kept track of all of this?  And wouldn’t it be even better if that component could tell us when it’s time for us to clamp down and stop burning cycles?


In fact, that component does exist, and it can tell you what’s going on in the system.  The component is Power Manager and it has a mechanism for signaling you whenever a System Power State transition happens.  (If you’re asking, “What’s a System Power State transition?” go back and read Power to the System again.)



That’s a lot of states
So, what’s the best way to deal with the fact that there are seven different System Power States, some used only on Pocket PC, some used only on Smartphone, and some overlapping?  Easy answer: “Don’t.”  You only need to worry about one state.  If the system is in the “On” state, you can animate.  If it’s not, don’t.  This is nice and clean and safe.  If in the next version we add some bizarre new state that happens in weird circumstances, your code will continue to work (because it’s unlikely you’ll want to be animating while in that state). 


Note that you do want to stop animating every time the system tells you that it’s no longer in the On state.  But you do not want to start animating whenever it tells you that it has switched back to the On state.  What if your app isn’t in the foreground?  There may be cases where you have to do this, but, by default you should think of this as a way to turn animations off, not to turn them on.



Sounds great.  Where do I sign up?
Hold on.  Things aren’t quite as rosy as they may seem.  I’ll bet you’re thinking you can use this mechanism for stopping your animations when the backlight goes off.  Unfortunately, there is no ideal way to do that.  First, the BacklightOff state didn’t get added until WM5.  So you won’t even hear about a state transition when the backlight goes off in WM 2003 SE and previous versions. 


Second, in the safe way to use this method, the “BacklightOff” state is represented as “On.”  There are documented flags for the different states, and, since they’re documented, you can rely on them.  And On and BacklightOff use the same flags. 


Now, if you like to live on the edge, there is also a string that gives the state’s name.  If you read that string, you can tell the difference between On and BacklightOff.  Trouble is, the definition of those strings is not documented.  That means that they could be changed in the future.  And that means that, if you rely on them, your code could break.  Yes, this sucks. 


However, if you use this technique, you will know if the screen goes off on SP and if the system goes to sleep on PPC.  And those are very good times to turn your animation off. 



Damn the torpedoes, we’re going multithreaded!
So, let’s talk about the real reason I’m describing this technique in “part 2: the hard way.”  In the end, getting notified that a state transition happens requires that you wait on an event.  And that pretty much requires that you spin up a thread to do it. 


Writing multithreaded code is hard.  If you’ve never done it before, I suggest against your first attempt being the code that you’re relying on to not annihilate your user’s battery life.  Yes, it would have been great if we’d made Power Manager send windows messages.  Yes, it would have been fantastic if we’d written a managed wrapper for it.  We didn’t. 


Also, I’m a system/drivers developer.  I write managed code in my spare time.  The pInvokes required to do this in managed code are just beyond my capabilities.  I can show you how to do it in Native, but Managed is out for this technique.  At least for now.


I’ve updated the AnimateSample to show how to do this.  In the Native directory you’ll find an “Animate3” alongside the existing Animate2.  I made 3 by copying 2 and then adding in the PowerManager stuff.  So you should be able to Windiff the two .cpp files and see just what’s changed.  I’m pretty sure I wrote more lines of comments than I did lines of code, so hopefully it’s understandable.



This is the end…
This is the last of my power entries.  I hope you found them informative.  Of course, if they generate enough questions to justify a new entry (as apposed to just answering them in comments) I’ll do an answers one.


Mike Calligaro


Comments (30)

  1. Riki says:

    Firstly, thanks so much for these articles.

    "So you won’t even hear about a state transition when the backlight goes off in WM 2003 SE and previous versions. "

    GetSystemPowerState() and GetDevicePower(L"BKL1:", …) are your friends!

    But what i want to know is how to get notified when a 2k3 device powers up again.

    Riki

  2. HeroreV says:

    Power to the developers?! Is that why you layered OpenGL over DirectX in Windows Vista?!

    Microsoft really has balls to try to force developers to use Direct3D and then talk about giving them power.

  3. windowsmobile says:

    Riki, you’re right that GetSystemPowerState and GetDevicePower will tell you what’s happening with the backlight. I’m not a huge fan of those techniques, though, because they require that you poll, which burns CPU, which is exactly what I’m telling people not to do.

    If you do them well, (only polling while the backlight is on, never while it’s off), they’re workable.

    As for getting notified when the PPC device powers on, try the code I posted and let me know if it works for you. I think it’ll do what you’re looking for.

    Watch out, though. I discovered a bug in the code this morning. If you downloaded it last night, please re-download.

    Mike Calligaro

  4. windowsmobile says:

    HeroreV, there are 60,000 people working at Microsoft. If you think every one of us shares shares the same consciousness and that we are all involved with every decision … well that’s just not how it is.

    This blog is for Windows Mobile technologies. We run on Windows CE, which is not the same operating system as Windows Vista. I assure you that the people here have no input on any decisions regarding how to implement OpenGL there. Your message might be better heard in one of the many Windows Vista blog sites.

    Mike Calligaro

  5. Hudson McCue says:

    Thank you for the most excellent series of articles on power management. Very informative and very helpful.

    Playing around with a PPC2003 device, I’ve noticed the following:

    1. device cradled, AC power, no ActiveSync – if there’s no ActiveSync connection the device display is turned off at the proper timeout set through the control panel power settings.

    2. device cradled, AC power, ActiveSync present – if there’s an ActiveSync connection, even one that’s not actively sync’ing (ie set to manual sync), the device display never turns off, or at least not on the timeout given by the control panel power setting.

    3. device cradled, no AC power, ActiveSync present – here the display turns off according to the setting, and it will stay off even while ActiveSync syncs.

    Can you lend any insight into what’s going on here under the hood? Is the presence of ActiveSync (or general network) traffic something the PM uses to make state change decisions only when on AC power?

  6. windowsmobile says:

    I’m glad you enjoyed them, Hudson.

    Apps have a way to keep a PocketPC from falling asleep (SystemIdleTimerReset). When ActiveSync is connected and there is AC power, it is calling that routine frequently enough to keep the device awake.

    When AC power is not present, I believe that ActiveSync will call SITR while it is syncing, but not when it has nothing to do. So it should stay on for the first sync and then suspend. I’m surprised to hear that the device is still syncing after the device has suspended, though. That shouldn’t happen.

    Mike Calligaro

  7. AndrewT says:

    Mike, thanks very much for the power management series, most helpful.

    However… I’m trying to use the power manager RequestPowerNotifications() approach but I never seem to get notified on my device (Orange C500) – is support for the notifications OEM-dependent?

    Regards,

    Andrew

  8. windowsmobile says:

    Andrew, I’m glad you enjoyed the series.

    The notifications are definitely not OEM dependent. Any WM 2003 or later device should get them. Can you take the Animate3 sample (I’ve updated it recently, so please re-download to be sure) does it work there? You should be able to put a breakpoint on the ReadMsgQueue line and see it get hit when the screen goes off.

    If that doesn’t work let’s follow up offline.

    Mike Calligaro

  9. AndrewT says:

    Mike,

    I’ve tried the latest Animate3 sample and still no joy. Unfortunately I can’t actually debug the thing live as the C500 charges via USB so as soon as you hook it up the device never sleeps. However, I’ve added some tracing and I’m pretty certain I don’t get any notifications at all.

    I’d appreciate any help you can give me on this. If you would rather continue offline, you can mail me at andrew AT lightbulbsoftware DOT com.

    Thanks,

    Andrew.

  10. Ed Bryan says:

    First, thanks for the code. I was using it in my app and it worked great. But then as I added more code for when the device is powering off, I noticed that sometimes all of my code does not get run. I am guessing that the CPU shuts down in the middle of my code. Could I use PowerPolicyNotify(PPN_UNATTENDEDMODE, 1) around my code to keep the CPU from going to sleep or would that be a bad thing in the PowerNotificationThread?

  11. windowsmobile says:

    Andrew and I dug into the issues he was having on his C500. What I’ve discovered is that, prior to WM5, power notifications don’t come through for UserIdle. That means that the extra complexity in Animate3 just isn’t worth it for pre-WM5 smartphones. PocketPC and WM5 Smartphones should still be able to take advantage of the power notifications, though. Sorry for the confusion.

    Mike Calligaro

  12. windowsmobile says:

    Hi Ed. Although the power notification stuff allows an App to know when the system is suspending, the general design of Windows CE is that apps aren’t involved in the suspend process. We wanted the device to turn off quickly when the user hit the power button, and didn’t want user mode apps to be able to slow that process down. Yes, there are other ways we could have handled this, but … well we didn’t.

    As such, there’s no guarantee that your app will get the notification of the change to suspended and have time to do anything about it. The general idea is that you should be processing things on wakeup, not suspend.

    If you have code running that you want to protect from a sleep, the Unattended call you posted will do the right thing. But that will only stop the system from suspending if the user hits the power button. If the system times out, it’ll still suspend. This means that your app still needs to be calling SystemIdleTimerReset when in Unattended.

    If the system is already suspending, it’s too late to try to stop it. Even if you could, there’s no guarantee that you’d run at all before the suspend.

    What is your app trying to do before suspend?

    Mike Calligaro

  13. WayneP says:

    Mike,

    On another tack, I need to sense when power is applied to the device and then power-on the device.  This is for a navigation application that needs to sense the power being supplied by the car-kit and then power on the device.

    Wayne Pienaar

  14. MikeCal says:

    Wayne, is the device a PocketPC or a Smartphone?  And, are you an ISV or an OEM?

    There’s no way for an ISV app to notice when a powered off smartphone is plugged in.  Some PocketPCs will be possible, others won’t.  

    If you’re an ISV and it’s a PocketPC, then the RequestPowerNotifications in Animate3 is your best bet.  If the device is one that wakes up when power is applied, you’ll get that notification.  If it’s not, your only recourse is to work with the OEM to make it happen.  All this code happens at the OEM level.

    Mike

  15. Seraph says:

    I am puzzled with the calls of functions XXX_PowerOn or XXX_PowerDown in some drivers. Are they called when system resume or suspend? Who will call them?

  16. MikeCal says:

    Seraph, those functions predate Power Manager and are generally only used on drivers that are not Power Manager aware.  They are called by the system during suspend and resume.  However, what they can do is extremely limited.  During the time when they are called, the system is single threaded.  This means that the calls can not make any system calls, not even to the registry.  Also, the system can’t take a page fault at this point, so these calls force the driver to be non-pageable.  

    Power Manager gives the driver a cleaner way to handle this situation.  PM puts drivers into D4 before the system goes single threaded, so the driver can make system calls, etc.  For this reason, Power Manager aware drivers tend to use that mechanism instead and don’t export the XXX_PowerOn and XXX_PowerDown routines.

    Mike

  17. There’s been a fair amount of interest in an offhand comment I made recently about saving a lot of standby…

  18. TommyS says:

    I want to have a test when the PDA powers up if it has been suspended for more than one hour. If it has the user must re-authenticate. I thought that I could write the time of Suspend to file, and check it when it powers on. But as I read now It is possible that the writing to file will not be done before the the terminal wakes up again.

    What will be the best way to solve this.

    Using a WM 5.0 device

  19. Joao says:

    Is it possible to set the device to keep the wireless circuit in such a state that it can wake up the device upon receiving something?

    Can the device be programmed to wake up directly into unattended mode in those circumstances?

    I am building an application that, in ideal mode, it would be able to keep an open TCP connection and react in realtime to data events sent through that TCP connection. I noticed that TCP connections via wireless keep alive for more than 3 minutes even if the device enters suspension.

    Thanks

  20. Joao says:

    Is it possible to set the device to keep the wireless circuit in such a state that it can wake up the device upon receiving something?

    Can the device be programmed to wake up directly into unattended mode in those circumstances?

    I am building an application that, in ideal mode, it would be able to keep an open TCP connection and react in realtime to data events sent through that TCP connection. I noticed that TCP connections via wireless keep alive for more than 3 minutes even if the device enters suspension.

    Thanks

  21. MikeCal says:

    Joao, the answer to your question depends on the following.

    By "Wireless" do you mean WiFi or Cellular?

    Is the device you’re using a Touch Screen (PocketPC) or a non-Touch (Smartphone) one?  

    On a PocketPC, WiFi is typically powered off when the device suspends.  So there is no way to receive anything over WiFi when suspended.  

    Smartphones never suspend, so WiFi can be kept running.  However, many OEMs shut WiFi down if it hasn’t been used after some period of time.

    It’s possible to wake on cellular on both PocketPC and Smartphone.

    Mike

  22. Nishant says:

    Hi Mike,

    Thanks for sharing such valuable information. It helped a lot in understanding power notifications in windows mobile.

    We were trying to get power notification when we switch off the display in Windows mobile 2003 SE Pocket PC MDA but we did not get the notification. In the code we changed the RequestPowerNotifications for POWER_NOTIFY_ALL to get all notifications. And we put the messagebox to notify us when notification occurs. Also we are getting flag value as 0 when we close the application and 0 seems to be the default value.

    Can you please throw the lights on why its not giving the notification for display off. Is it because of compatibility issue or because any changes we made.

    Thanks,

    Nishant

  23. MikeCal says:

    Nishant, how are you turning off the display?  Are you hitting the power button and putting the device to sleep, or are you programmatically calling an API that turns the screen off?

    Mike

  24. Ramesh says:

    We are developing the device driver for SDIO-UART in Embedded CE for Windows Mobiles.

    When the SDIO-UART kit is inserted in SD-Slot the driver will load automatically.

    Up to this working good, when we soft-reset(warm-boot) the PDA while the card is in inserted condition, the PDA failed to load the driver. After the re-insertion of card only driver is loaded.

    But according to our requirement, the SDIO-UART based serial device always inserted in the SD slot.

    What we will do?

    Similarly for the Sleep mode also, the PDA won’t wakeup when the SDIO-UART kit inserted condition.

    The only solution is soft-reset the PDA; and re-insert the SDIO-UART kit.

    Is there any work around need to do for soft reset and sleep mode issue.

    Thanks in Advance.

    Best Regards,

    Ramesh.

    India.

  25. Dan says:

    Hi,

    just wanted to point out that the AnimateSample.zip download URL is not working anymore – is there a copy of the file available somewhere else?

    Thx,

    Dan

  26. Miro says:

    Hi,

    I just wonder if there is any event or a any other way, to know that the device is idle, when it is in cradle (external power) and the user disabled auto-off for both backlight and the device?

    Regards,

    Miro

  27. kos says:

    Hey is there a way to get wifi to be enabled when a pocket pc (htc touch) goes into standby? If so what functions in the registry do you have to change. I was able to change around some values in the default and NDIS modes but nothing happened? I removed the key "Power-manageable NDIS miniports". I was able to turn on the wifi but when I turn the screen back on from the suspend mode the wifi ends up frozen and does not connect until I turn it off and on again? Can anyone help?

    thanks,

    Kos

  28. Over the years, I’ve delivered several “Top 10” sessions and called them different things. Top Snafus,

  29. Radu Motisan says:

    Hello Mike, thanks for taking the time to share this knowledge.

    Regarding your PowerNotificationThread . Quite an old implementation, taken from the shelf with useful samples, isn’t it? :-)

    I remember while working with an OEM, 3-4 years ago, they’ve sent me this function as a sample, to help me improve the power consumption, by shutting down all active threads in my app, on a WM5.0 Smartphone.

    A few years later, I’m getting back to this.

    Flags in POWER_BROADCAST, as returned with pbMsgBuf, looks a bit odd.

    In your Animate2&3 samples, I see you’ve only used

    ((pPower->Flags & POWER_STATE_ON) == 0) however, one might require additional features like knowing:

    -when the device is turned on

    -when the device going backlight off

    etc

    Please provide more on this.

    A few test results:

    HTC Hertz, WM5.0

    1 – on backlight off, Flags comes as 0x10010000

     – string name is "backlightoff"

    2 – on key press, backlight turns on, Flags = 0x10010000

     – string name is "on"

    HTC Universal, WM6.1

    1 – on backlight off, Flags is 0x10010000

     – string name is "backlightoff"

    2 – on key press, bcklight turns on, Flags = 12010000

     – string name is "on"

    The Hertz smartphone is acting weird, 1 and 2 return same flag, but different string names.

    At this point, the string name seems most reliable, still I wouldn’t use that.

    First issue. How to interpret the Flag for backlight off, when the only options are:

    #define POWER_STATE(f)           ((f) &  0xFFFF0000)        // power state mask

    #define POWER_STATE_ON           (DWORD)(0x00010000)        // on state

    #define POWER_STATE_OFF          (DWORD)(0x00020000)        // no power, full off

    #define POWER_STATE_CRITICAL     (DWORD)(0x00040000)        // critical off

    #define POWER_STATE_BOOT         (DWORD)(0x00080000)        // boot state

    #define POWER_STATE_IDLE         (DWORD)(0x00100000)        // idle state

    #define POWER_STATE_SUSPEND      (DWORD)(0x00200000)        // suspend state

    #define POWER_STATE_UNATTENDED   (DWORD)(0x00400000)        // Unattended state.

    #define POWER_STATE_RESET        (DWORD)(0x00800000)        // reset state

    #define POWER_STATE_USERIDLE     (DWORD)(0x01000000)        // user idle state

    #define POWER_STATE_PASSWORD     (DWORD)(0x10000000)        // This state is password protected.

    Second question. Are you aware of any way of waking the device up from "backlight off mode", the equivalent of pressing a key?

    1-SystemIdleTimerReset(), prevents the device from getting into "backlight off" mode, but it doesn’t help turning the backlight back on

    2-SetSystemPowerState(0, POWER_STATE_ON, POWER_FORCE), doesn’t always work, and if it works, the device won’t get back to "backlight off" too early. the default behaviour must not be altered.

    3-SetPowerRequirement/ReleasePowerRequirement, a nice approach, but we only need to wake the device once,then to let the device get back to it’s idle-mode control

    Indeed all these would only need an additional timer. But I don’t want to use a timer. I only need to wake the backlight similar to what happens when a user presses a key.

    Regards,

    Radu Motisan

  30. Hi All,

    I am facing a strage problem. I have a Treo 700 Wx Sprint device, when i keep it on AC power charging for say an overnight then in morning it is in locked state. I have to soft reset the device. Can anyone suggest me the reason or resoltuion of the issue,

    Thanks in advance.