Windows* WM_POWERBROADCAST Messages in a Mobilized Environment

by Lester Memmott


Introduction

In an ideal world, mobile systems would run all day without requiring the support of AC power – and with the recent launch of Intel® Centrino® Mobile Technology this is becoming closer to reality. However, in addition to the advances in hardware, software developers can now make applications power-aware by handling the WM_POWERBROADCAST message provided by the Windows* Operating System and scaling features accordingly. This whitepaper describes how to handle the WM_POWERBROADCAST message and also describes the sequence of messages for four typical cases. Additional introductory material is available from the MSDN documentation at http://msdn.microsoft.com*. MSDN, however, does not describe the expected sequence of messages in the event of AC power loss, AC power reconnect, system standby and natural battery depletion when off of AC power. These areas are explored here with a detailed analysis.


Definitions

WM_POWERBROADCAST: Microsoft Windows Operating System message sent to applications to indicate system-wide power state changes.

AC Power: High voltage power supplied to a mobile system by plugging into a power outlet. This act, generally, recharges the system battery.

MSDN: Microsoft Developer Network. See http://msdn.microsoft.com*


Background

Hardware advances have made mobile systems lighter and more energy efficient. In addition to these advances, software developers can make applications power-aware such that they enable users to work for longer periods of time before having to reconnect to recharge the system battery. For example, when on AC power, an anti-virus scanner would run full-featured, providing file scanning on all files opened and also running periodic system wide scans. When on battery power the scanner could defer the system wide scans until a later time and continue processing safely, analyzing just the open files.

Under the Windows Operating System, applications are notified of system power changes through the WM_POWERBROADCAST message. Note that the WM_POWER message is now obsolete and should be replaced with WM_POWERBROADCAST. These messages are handled through the standard message loop using GetMessage(). A sample application provided with this whitepaper shows a reference implementation for the concepts presented.

The WM_POWERBROADCAST comes with two parameters: wParam & lParam. The wParam can be a number of items which specifies the event received. The documentation for each of these is provided at MSDN as:

Event Meaning
PBT_APMBATTERYLOW Battery power is low.
PBT_APMOEMEVENT OEM-defined event occurred.
PBT_APMPOWERSTATUSC HANGE Power status has changed.
PBT_APMQUERYSUSPEND Request for permission to suspend.
PBT_APMQUERYSUSPENDFAILED Suspension request denied.
PBT_APMRESUMEAUTOMATIC Operation resuming automatically after event.
PBT_APMRESUMECRITICAL Operation resuming after critical suspension.
PBT_APMRESUMESUSPEND Operation resuming after suspension.
PBT_APMSUSPEND System is suspending operation.

 

The lParam is function specific and is not generally used.

Knowing that these messages can be received is beneficial, but it is more helpful to understand the expected sequence of these events when undergoing normal system transitions. The transitions analyzed are:

  • AC Power disconnect
  • AC Power reconnect
  • A running system goes into standby and is powered backup
  • The battery is drained from a full charge to a 0%.

The following sections show the results using a Dell Latitude* P4-M 2.4 GHz laptop. The data was captured using Spy++*, a tool installed with MSVC which allows Windows messages to be monitor for a specific running application. For each case described, capturing the data was done using the following steps:

  1. Launch Notepad and Spy++ (Spy++ is located under the Microsoft Visual Studio Tools, under Start -> All Programs.)
  2. In Spy++, Spy -> Messages
  3. Using the Finder Tool, drag and drop the cross-hairs from the Windows tab on the window for Notepad.
  4. Check the boxes for: Parent, Children, Windows of Same Thread, Windows of Same Process.
  5. In the Message Tab, click “Clear all”, then select WM_POWERBROADCAST.
  6. In the Output Tab, check the box for “Also Log in File” and provide a file name.
  7. Click OK.
  8. After running test outlined below, Press F8 (or Messages -> Stop Logging) to stop logging messages.

The data provided is the following:

  1. Line Number
  2. Message Nesting Level
  3. Message Code
    • P = Message posted to queue with PostMessage()
    • S = Message sent using SendMessage()
    • R = Return value (Grouped with S codes)
  4. Decoded Message Parameter (always WM_POWERBROADCAST for these tests)
  5. lParam
  6. wParam

 

Analysis

Case 1: AC Power Disconnect

This test was run by running Spy++ as outlined above and then removi ng AC power. Items in italic are commentary added to the Spy++ output.

Test Sequence

System on AC Power
Disconnect Power Cable

<00001> 000501B4 P WM_POWERBROADCAST (long)dwPowerEvent:PBT_APMPOWERSTATUSCHANGE dwData:00000000

Analysis

  • The WM_POWERBROADCAST message by itself doesn’t provide enough details to know that AC power was disconnected. When the message is received, GetSystemPowerStatus() must be called to get the details.


Case 2: AC Power Connect

This test was run by starting Spy++ as outlined above and then connecting AC Power. Items in italic are commentary added to the Spy++ output.

Test Sequence
On Battery Power
Connect AC Power Cable
<00001> 000501B4 P WM_POWERBROADCAST (long)dwPowerEvent:PBT_APMPOWERSTATUSCHANGE dwData:00000000
<00002> 000501B4 P WM_POWERBROADCAST (long)dwPowerEvent:PBT_APMPOWERSTATUSCHANGE dwData:00000000
<00003> 000501B4 P WM_POWERBROADCAST (long)dwPowerEvent:PBT_APMPOWERSTATUSCHANGE dwData:00000000

Analysis

  • The WM_POWERBROADCAST message by itself doesn’t provide enough details to know that AC power was reconnected. When the message is received, GetSystemPowerStatus() must be called to get the details.


Case 3: Standby and Resume

This test was run by starting Spy++ as outlined above, putting the system into standby mode and then starting the system backup again. Items in italic are commentary added. The system was on AC power the whole item.

Test Sequence

Start Standby Process
<00001> 000201FA S WM_POWERBROADCAST (long)dwPowerEvent:PBT_APMQUERYSUSPEND dwData:00000001
<00002> 000201FA R WM_POWERBROADCAST fSucceeded:True (//Return true to indicate that suspend is OK.)
<00003> 000201FA P WM_POWERBROADCAST (long)dwPowerEvent:PBT_APMPOWERSTATUSCHANGE dwData:00000000
<00004> 000201FA S WM_POWERBROADCAST (long)dwPowerEvent:PBT_APMSUSPEND dwData:00000000
<00005> 000201FA R WM_POWERBROADCAST fSucceeded:True
<00006> 000201FA R WM_POWERBROADCAST fSucceeded:True
System now in standby mode
<00007> 000201FA S WM_POWERBROADCAST (long)dwPowerEvent:PBT_APMRESUMESUSPEND dwData:00000000
<00008> 000201FA R WM_POWERBROADCAST fSucceeded:True
<00009> 000201FA P WM_POWERBROADCAST (long)dwPowerEvent:PBT_APMPOWERSTATUSCHANGE dwData:00000000
<00010> 000201FA P WM_POWERBROADCAST (long)dwPowerEvent:PBT_APMPOWERSTATUSCHANGE dwData:00000000
<00011> 000201FA P WM_POWERBROADCAST (long)dwPowerEvent:PBT_APMPOWERSTATUSCHANGE dwData:00000000
System now powered back up

Analysis

  • Going into standby sequence of messages is:
    • PBT_APMQUERYSUSPEND (dwData: 00000001)
    • Return True to indicate that a system suspend is OK.
    • PBT_APMPOWERSTATUSCHANGE (dwData: 00000000)
    • PBT_APMSUSPEND (dwData: 00000000)
  • Coming out of standby sequence of messages is:
    • PBT_ APMRESUMESUSPEND (dwData: 00000000)
    • PBT_ APMPOWERSTATUSCHANGE (dwData: 00000000)
    • PBT_ APMPOWERSTATUSCHANGE (dwData: 00000000)
    • PBT_ APMPOWERSTATUSCHANGE (dwData: 00000000)
In response to PBT_ APMQUERYSUSPEND an application can stop the system from going into suspend mode. MSDN documentation provides details on how this is done.

Case 4: Battery from 100% to Critical State

This test was run by charging the system to 100% battery, starting Spy++ as outlined above and then discharging the battery over time. To accelerate the discharge rate a batch file repetitively copied files from a DVD to the hard drive and a hard drive search was done for all files containing a long random string. Items in italic are commentary added.

Test Sequence

Disconnect Power
<00001> 000201FA P WM_POWERBROADCAST (long)dwPowerEvent:PBT_APMPOWERSTATUSCHANGE dwData:00000000
<00002> 000201FA P WM_POWERBROADCAST (long)dwPowerEvent:PBT_APMPOWERSTATUSCHANGE dwData:00000000
<00003> 000201FA P WM_POWERBROADCAST (long)dwPowerEvent:PBT_APMPOWERSTATUSCHANGE dwData:00000000
<00004> 000201FA P WM_POWERBROADCAST (long)dwPowerEvent:PBT_APMPOWERSTATUSCHANGE dwData:00000000
<00005> 000201FA P WM_POWERBROADCAST (long)dwPowerEvent:PBT_APMPOWERSTATUSCHANGE dwData:00000000
<00006> 000201FA P WM_POWERBROADCAST (long)dwPowerEvent:PBT_APMPOWERSTATUSCHANGE dwData:00000000
<00007> 000201FA P WM_POWERBROADCAST (long)dwPowerEvent:PBT_APMPOWERSTATUSCHANGE dwData:00000000
<00008> 000201FA P WM_POWERBROADCAST (long)dwPowerEvent:PBT_APMPOWERSTATUSCHANGE dwData:00000000
<00009> 000201FA P WM_POWERBROADCAST (long)dwPowerEvent:PBT_APMPOWERSTATUSCHANGE dwData:00000000
<00010> 000201FA P WM_POWERBROADCAST (long)dwPowerEvent:PBT_APMPOWERSTATUSCHANGE dwData:00000000
<00011> 000201FA P WM_POWERBROADCAST (long)dwPowerEvent:PBT_APMPOWERSTATUSCHANGE dwData:00000000
<00012> 000201FA P WM_POWERBROADCAST (long)dwPowerEvent:PBT_APMPOWERSTATUSCHANGE dwData:00000000
<00013> 000201FA P WM_POWERBROADCAST (long)dwPowerEvent:PBT_APMPOWERSTATUSCHANGE dwData:00000000
<00014> 000201FA P WM_POWERBROADCAST (long)dwPowerEvent:PBT_APMPOWERSTATUSCHANGE dwData:00000000
<00015> 000201FA P WM_POWERBROADCAST (long)dwPowerEvent:PBT_APMPOWERSTATUSCHANGE dwData:00000000
<00016> 000201FA P WM_POWERBROADCAST (long)dwPowerEvent:PBT_APMPOWERSTATUSCHANGE dwData:00000000
<00017> 000201FA P WM_POWERBROADCAST (long)dwPowerEvent:PBT_APMPOWERSTATUSCHANGE dwData:00000000
<00018> 000201FA P WM_POWERBROADCAST (long)dwPowerEvent:PBT_APMPOWERSTATUSCHANGE dwData:00000000
<00019> 000201FA P WM_POWERBROADCAST (long)dwPowerEvent:PBT_APMPOWERSTATUSCHANGE dwData:00000000
<00020> 000201FA P WM_POWERBROADCAST (long)dwPowerEvent:PBT_APMPOWERSTATUSCHANGE dwData:00000000
<00021> 000201FA P WM_POWERBROADCAST (long)dwPowerEvent:PBT_APMPOWERSTATUSCHANGE dwData:00000000
<00022> 000201FA P WM_POWERBROADCAST (long)dwPowerEvent:PBT_APMPOWERSTATUSCHANGE dwData:00000000
<00023> 000201FA P WM_POWERBROADCAST (long)dwPowerEvent:PBT_APMPOWERSTATUSCHANGE dwData:00000000
<00024> 000201FA P WM_POWERBROADCAST (long)dwPowerEvent:PBT_APMPOWERSTATUSCHANGE dwData:00000000
<00025> 000201FA P WM_POWERBROADCAST (long)dwPowerEvent:PBT_APMPOWERSTATUSCHANGE dwData:00000000
<00026> 000201FA P WM_POWERBROADCAST (long)dwPowerEvent:PBT_APMPOWERSTATUSCHANGE dwData:00000000
<00027> 000201FA P WM_POWERBROADCAST (long)dwPowerEvent:PBT_APMPOWERSTATUSCHANGE dwData:00000000
<00028> 000201FA P WM_POWERBROADCAST (long)dwPowerEvent:PBT_APMPOWERSTATUSCHANGE dwData:00000000
<00029> 000201FA P WM_POWERBROADCAST (long)dwPowerEvent:PBT_APMPOWERSTATUSCHANGE dwData:00000000
<00030> 000201FA P WM_POWERBROADCAST (long)dwPowerEvent:PBT_APMPOWERSTATUSCHANGE dwData:00000000
<00031> 000201FA P WM_POWERBROADCAST (long)dwPowerEvent:PBT_APMPOWERSTATUSCHANGE dwData:00000000
<00032> 000201FA P WM_POWERBROADCAST (long)dwPowerEvent:PBT_APMPOWERSTATUSCHANGE dwData:00000000
<00033> 000201FA P WM_POWERBROADCAST (long)dwPowerEvent:PBT_APMPOWERSTATUSCHANGE dwData:00000000
<00034> 000201FA P WM_POWERBROADCAST (long)dwPowerEvent:PBT_APMPOWERSTATUSCHANGE dwData:00000000
<00035> 000201FA P WM_POWERBROADCAST (long)dwPowerEvent:PBT_APMPOWERSTATUSCHANGE dwData:00000000
<00036> 000201FA P WM_POWERBROADCAST (long)dwPowerEvent:PBT_APMPOWERSTATUSCHANGE dwData:00000000
<00037> 000201FA P WM_POWERBROADCAST (long)dwPowerEvent:PBT_APMPOWERSTATUSCHANGE dwData:00000000

The system issued an alert indicating that AC power should be connected

Note that the messages above were sent at even periodic intervals through the discharge cycle.

Analysis

The WM_POWERBROADCAST message by itself doesn’t provide enough details to know that AC power was disconnected or reconnected. When the message is received, GetSystemPowerStatus() must be called to get the details.


Conclusion

  • In all cases WM_POWERBROADCAST is simply to inform that something has changed, but it doesn’t specify what has changed. GetSystemPowerStatus() must be called to know what the current power status is.
  • If it is important for the application to know what the transition is from, a state variable must be maintained from the previous call to GetSystemPowerStatus(). The previous state and the current state would then be compared to determine what specifically has changed.
  • Suspending a system comes in two parts, a request to suspend and then a notification that suspend is about to happen. Suspend can be stopped by any one application on the system.

 


References and Additional Resources

 

Articles

 

Developer Centers

Community

 

Other Resources

 


Download the PDF (133KB)

 

Categories:
For more complete information about compiler optimizations, see our Optimization Notice.