I'm a frequent reader of the MSDN Smartdevices forum. In reading through the questions that others have I see some reoccurring questions related to power management on Windows Mobile devices. The questions can be generally classified into one of two groups; the first group for questions on preventing certain power saving measures from occuring and the second on writing programs that preserve the devices battery life much better. I'll run through a few of the questions here but if you would like more details on power management on Windows Mobile see the article mentioned at the end of this post.
Questions on preserving battery life ususally start off with some other question in which the developer post a code sample to make his or her question understood. Another community member will point out the battery killing behaviour in the posted code and then continue to explain how to correct it. To understand how software can impact battery life we first need to look at the typical behavior of a user application. When a user application is running it spends a majority of its time waiting. It could be waiting on the user to press the next letter of a word being type, waiting for an IO request to complete, or waiting for some system event to occurr. When an event occurs the program responds to the event and then goes back to waiting. Windows Mobile devices take advantage of this behaviour by placing the CPU in an extremely low power state when there's nothing to do.
Now consider the following:
parital class MyMainForm : Form
{
bool taskCompleteFlag = false;
string finalResult = null;
void BeginTask()
{
Thread t = new Thread(new ThreadStart(MyTask) );
t.Start();
while(taskCompleteFlag!=true)
{
//Do nothing!
}
MessageBox.Show(finalResult);
}
}
In the above code the main thread of a program creates a worker thread and then spins on a variable repeatedly checking to see if the worker thread has completed. There are other forms of this pattern (also known as the "busy waiting" anti-pattern) in which the code spins on the state of an IO buffer, a lock, or some other system state. While the implementation of this pattern varies the affect is the same; the thread is unnecessarily asserting bus cycles to check the variable and utilizing a high percent of the CPU's bandwidth to essentially perform no work. The device's power manager will see that the CPU is not idle and won't place it in a lower power state significantly impacting the battery life of the device. Such coding practices are especially devestating to a Windows Mobile Standard device. Windows Mobile Standard devices are always on so the above pattern could keep the CPU in a higher power state until the device's battery is empty. On a Windows Mobile Professional device after so many minutes of user inactivity the device will suspend. But the unnecessarily high CPU utilization of the above code could still result in higher battery consumption when the device is not in a suspended state.
The same functionality can be achieved through .Net events, Windows events, joining threads, and other mechanisms that will allow a thread to wait on something to occur while not wasting CPU cycles. For some events a program does not need to even be in memory while it waits on its event. The native function call CeRunAppAtEvent or CeRunAppAtTime can be used to register a program to be started on certain events or at a specific time (For more information on automatically launching your program on an event see this article)
Programs that require a Windows Mobile device not use certain power saving behaviours must be proactive about requesting what they need. The requests can only be made through P/Invoke calls to the native Windows functions since the .Net Compact Framework does not yet expose any power managment related classes. But most of the functions have simple When a user is not directly interacting with a Windows Mobile device it will turn of the screen backlight and then the screen. For Windows Mobile Professional devices the device will later go into a suspended state which will pause all running threads. Some applications need for the device to continue to run without slipping into lower power states from user inactivity; media players and GPS navigation software are both examples of applications that may need to run for a long period without user input. For both cases a program can prevent the device from entering a lower power state by periodically calling the SystemIdleTimerReset() function.
There are also programs that may need to perform work in the background but should allow the device to power down as much as possible while still satisfying the power needs of the program. Such a program would need to run in "unattended" mode (through the PowerPolicyNotify function) and request that the OS keep the hardware that it plans to use powered and then release it's requests when it has finished working.

For both Windows Mobile Professional and Windows Mobile standard devices a program can
query the battery state. GetBatteryStatusEx2() can be used to acquire almost any information available on the battery (it's type, temperature, voltage and current output and more) though not all devices return full information on the battery. The image in this post is from a screenshot of the battery example code that is included with my article.
There are other commonly asked questions and scenarios for power management on Windows Mobile. I've collected information that I believe will saitisfy a majority of the questions that I've seen and have made it available at The Code Poject. I'll be making updates to it with time to address reoccuring needs that are identified in the MSDN forums. My next update will occur some time this week in which I add a GPS related code example to the article.


0 comments:
Post a Comment