GPS and Suspend

Search This thread

Baffles

Member
Sep 12, 2007
47
26
I'm working on my code to keep GPS alive (today screen plugin, dunno if anyone ever posted it here but it's over at ppcgeeks). Turns out the qualcomm driver for the GPS in the Mogul crashes if the device goes to sleep when there is an open handle to the GPS device.

I did some quick hacking with SetPowerRequirement and it turns out the driver ignores power requirements.

At this point, my conclusions lead me to be pretty upset with HTC for once again passing ****ty drivers on to us. So I go to my last resort option, using RequestPowerNotifications. Spent a few hours debugging and getting the message loop working correctly, only to find out the PBT_TRANSITION message for suspension doesn't always come through before the device goes down.

Does anyone have any ideas on how to handle GPS and Sleep? I'd hate to do something to totally change the functioning of the device (like holding the whole device alive), but I can't really think of anything else to do.
 

TalynOne

Senior Member
Jun 25, 2007
309
39
Hi Baffles, I haven't documented this yet, I will soon...

In GpsGate v2.6.0.308, they added an "WM GPS" option for the "Input" source. When this is done then GpsGate primes the GPS on the Titan. Also when used in conjunction with the "Close input when idle" option in the "Advanced" section of the "Input" tab in GpsGate, then GpsGate only turns on the GPS when a GPS application request GPS data from the GpsGate output port. This behavior seems to survive suspend/wakeup just fine too. Maybe you can study how they handle it as a clue for your application.
 

mligor

Member
Oct 24, 2006
8
0
Frankfurt am Main
It took me a while, but on the end I got it to work...

Point is that you have to use Unattended mode

here is what you have to do:

1) call PowerPolicyNotify(PPN_UNATTENDEDMODE, TRUE)

this will tell to PowerManager that your application wants to do something before device go to sleep :) - will activate Unattended mode

2) SetPowerRequirement(L"GPS0:", D0, POWER_NAME|POWER_FORCE, NULL, NULL);

not sure if this is needed, but because we need GPS to stay alive it is ok to call it (if you use GPS over COM port, instead of GPS0: should be COMx:)


3) use RequestPowerNotifications(m_hMsgQueue, PBT_TRANSITION)

and create MessageQueue to get info when mode is changed... (look e.g. POWER_BROADCAST structure for more info).

4) you have to have one WaitForSingle/MultipleObjects with timeout, where you will wait for handle on MessageQueue you created for PBT_TRANSITION

5) when PBT_TRANSITION comes, and if device is changed in Unattended mode (simple string comparing POWER_BROADCAST.SystemPowerState=="unattended") you are responsible to keep device alive.. which mean you have to call periodically SystemIdleTimerReset() - if you do not do that, your device will go to sleep mode

do not call SystemIdleTimerReset() if you are not in unattended mode, because that will prevent device to switch off backlight and screen.

6) in case of timeout on WaitForXXObjects you can read GPS port and process your data

.. in general Unattended mode needs more power then sleep mode, but that is only way (at least on my HTC Artemis).

From documentation point of view simple call SetPowerRequirement(L"GPS0:", D0, POWER_NAME|POWER_FORCE, NULL, NULL) should be enough, but it is not so :(


I hope that will help you... my application works fine now and I'm happy :D

regards,
Igor
 

dannyboy78

Member
Feb 15, 2006
8
0
Thanks for that Igor, that all works for me as well. Tested on HTC P3300 and HTC P3600. I have also tried this on the HTC TyTnII but that deviceas always doesn't want to play nicely, as Baffles pointed out it does indeed seem to ignore calls to SetPowerRequirement.
If anyone has come across a way getting round the problems of the TyTnII, it would be great to hear it.

Thanks
Dan
 

negerzoen

New member
Jun 24, 2008
1
0
Unfortunately, I'm not able to keep the GPS signal alive on my HTC P3600 (Orange SPV M700). Unattended mode works; a timer remains active and a simpel counters counts through. However, the GPS signal disappears after pressing the power button.

I call PowerPolicyNotify and SystemIdleTimerReset on each timer tick. Then, I read all data from the serial port (COM9). This works fine. After I press the power button, there is no more data to read from the serial port.

I also tried the code Igor mentiones about the power notification. I had to use platform invokes because I'm using the .NET Compact Framework. This works; I receive a signal and I can read a message from the message queue. However, I don't see the entire point of creating a message queue en registering for power notifications. Is there anything you need to do on the transition event besides calling SystemIdleTimerReset periodically?

Please help me out!
 
Last edited:

luleyp

New member
Oct 9, 2007
2
0
same problem on P3650

Hi there,

I have the same problem on the HTC Polaris (P3650). I want to run my application in unattended mode with an open gps connection.... and I haven'T found a solution yet.

Could anyone who managed to do that pleas post a code example for that.

Thanks a lot.

Patrick
 

mligor

Member
Oct 24, 2006
8
0
Frankfurt am Main
Unfortunately, I'm not able to keep the GPS signal alive on my HTC P3600 (Orange SPV M700). Unattended mode works; a timer remains active and a simpel counters counts through. However, the GPS signal disappears after pressing the power button.

I call PowerPolicyNotify and SystemIdleTimerReset on each timer tick. Then, I read all data from the serial port (COM9). This works fine. After I press the power button, there is no more data to read from the serial port.

I also tried the code Igor mentiones about the power notification. I had to use platform invokes because I'm using the .NET Compact Framework. This works; I receive a signal and I can read a message from the message queue. However, I don't see the entire point of creating a message queue en registering for power notifications. Is there anything you need to do on the transition event besides calling SystemIdleTimerReset periodically?

Please help me out!

Hi, sorry for late answer....

In transition event you just need SystemIdleTimerReset.. basically that is what unattended mode is:

In Unattended mode.. you get transition event PBT_TRANSITION, where SystemPowerState is "unattended", and application can decide if will allow device to go to sleep or to call SystemIdleTimerReset...

I'm not sure how long "unattended" PowerState stays... but if you call often SysteIdleTimerReset, your app could work without MessageQueue (anyway I use message queue for monitoring power state, and if power is to low, I switch off GPS device).
 

mligor

Member
Oct 24, 2006
8
0
Frankfurt am Main
here is my code snippet - it is not guaranteed that is compilable, because I took parts from my application.... but should be enough to get overview what you have to do to make it to work.

About managed code.. I didn't try it.. somehow for me is still easier to write C++ code :p





Code:
static const DWORD maxMsgQueueMsgSize = sizeof(POWER_BROADCAST_POWER_INFO) + sizeof(POWER_BROADCAST) + MAX_PATH;

// create stop event
HANDLE hStopEvent = CreateEvent(NULL, FALSE, FALSE, NULL);

// create event for GPS change
HANDLE hDeviceStateChanged = CreateEvent(NULL, FALSE, FALSE, NULL);

// Create message queue
MSGQUEUEOPTIONS msgQueueOptions;
ZeroMemory(&msgQueueOptions, sizeof(msgQueueOptions));
msgQueueOptions.dwSize = sizeof(msgQueueOptions);
msgQueueOptions.dwFlags = MSGQUEUE_NOPRECOMMIT ;
msgQueueOptions.cbMaxMessage = maxMsgQueueMsgSize;
msgQueueOptions.bReadAccess = TRUE;

HANDLE hMsgQueue = ::CreateMsgQueue(NULL,  &msgQueueOptions);
HANDLE hPowerNotification = ::RequestPowerNotifications(hMsgQueue, PBT_POWERINFOCHANGE | PBT_TRANSITION);

// opening GPS device
HANDLE hGPSDevice = ::GPSOpenDevice( 0, hDeviceStateChanged, NULL, 0);

bool bRun = true; // run loop
bool bHasSignal = false; 

// change power requirement for GPS device and SD card
HANDLE hGPSPowerReq = ::SetPowerRequirement(L"GPS0:", D0, POWER_NAME|POWER_FORCE, NULL, NULL);
HANDLE hPowerReq = ::SetPowerRequirement(L"DSK1:", D0, POWER_NAME|POWER_FORCE, NULL, NULL);

// change to Unattended mode
::PowerPolicyNotify(PPN_UNATTENDEDMODE, TRUE);

// LOOOP
HANDLE events[3] = {hDeviceStateChanged, hStopEvent, hMsgQueue} ;
while (bRun)
{
	DWORD dwWaitRes = ::WaitForMultipleObjects(3, events, FALSE, 1000 ); // read every 1. sec.
	switch (dwWaitRes)
	{
	case WAIT_OBJECT_0:
		// device status changed
		{
			GPS_DEVICE dev;
			ZeroMemory(&dev, sizeof(dev));
			dev.dwVersion = GPS_VERSION_1;
			if (ERROR_SUCCESS == ::GPSGetDeviceState(&dev))
			{
				// do something... 
			}
		}
		break;
	case WAIT_OBJECT_0+1:
		// exit requested from exit event.. this is done from other thread by calling SetEvent(hExitEvent)
		bRun = false;
		break;
	case WAIT_OBJECT_0+2:
		// if we are on low power, stop monitoring
		{
			// there is a message in EventQueue.. read queue
			BYTE buffer[maxMsgQueueMsgSize];
			DWORD NumberOfBytesRead = 0;
			ZeroMemory(buffer, maxMsgQueueMsgSize);

			DWORD dwFlags;
			if (::ReadMsgQueue(m_hMsgQueue, buffer, maxMsgQueueMsgSize,&NumberOfBytesRead, 0, &dwFlags ) && NumberOfBytesRead>=sizeof(POWER_BROADCAST))
			{
				POWER_BROADCAST* pPwrBrodcast = (POWER_BROADCAST*)(buffer);
				switch(pPwrBrodcast->Message)
				{
				case PBT_POWERINFOCHANGE:
					{
						// if battery level is to low, finish with GPS reading
						POWER_BROADCAST_POWER_INFO* pPowerInfo = (POWER_BROADCAST_POWER_INFO*)pPwrBrodcast->SystemPowerState;
						if ((pPowerInfo->bBatteryFlag==2 || pPowerInfo->bBatteryFlag==4) && (pPowerInfo->bACLineStatus==0))
							bRun = false;
					}
					break;
				case PBT_TRANSITION:
					{
						std::wstring powerState = pPwrBrodcast->SystemPowerState;
						// handle power states
						if (powerState==L"resuming")
							::PowerPolicyNotify(PPN_UNATTENDEDMODE, TRUE); // basicaly should never happen, because we do not allow to go in 
						if (powerState==L"unattended")
							SystemIdleTimerReset();
					}
					break;
				default:
					ASSERT(!"Unknown message");
				}

			}
		break; 
	case WAIT_TIMEOUT:
		// new location
		break;
	}
	// DO SOMETHING... e.g. Read position from GPS PORT
}
// ENDLOOP

::PowerPolicyNotify(PPN_UNATTENDEDMODE, FALSE); // Leave unattended mode
::ReleasePowerRequirement(hGPSPowerReq);		// allow GPS device to go in sleep
::ReleasePowerRequirement(hPowerReq);

::GPSCloseDevice(hGPSDevice); // close GPS device

StopPowerNotifications(hPowerNotification);
CloseMsgQueue(hMsgQueue);
CloseHandle(hPowerNotification);
CloseHandle(hMsgQueue);
 

mligor

Member
Oct 24, 2006
8
0
Frankfurt am Main
Unfortunately, I'm not able to keep the GPS signal alive on my HTC P3600 (Orange SPV M700). Unattended mode works; a timer remains active and a simpel counters counts through. However, the GPS signal disappears after pressing the power button.

I call PowerPolicyNotify and SystemIdleTimerReset on each timer tick. Then, I read all data from the serial port (COM9). This works fine. After I press the power button, there is no more data to read from the serial port.

I also tried the code Igor mentiones about the power notification. I had to use platform invokes because I'm using the .NET Compact Framework. This works; I receive a signal and I can read a message from the message queue. However, I don't see the entire point of creating a message queue en registering for power notifications. Is there anything you need to do on the transition event besides calling SystemIdleTimerReset periodically?

Please help me out!

Just one more thing (or two)...

you read from COM9.. maybe you should try to call
SetPowerRequirement(L"COM9:", D0, POWER_NAME|POWER_FORCE, NULL, NULL);


in case that you press Power button.. device is going immediately into Unattended mode, and there is chance to miss that mode in case that you do not have MessageQueue, or maybe there is some kind of Windows optimization that if no applications are registered for PBT_TRANSITION, Unattended mode is skipped and device going immediately into Sleep.

You wrote that "there are no more data to read from COM port".. are you sure that your code is running?

in case that your code is still running, then you prevented Sleep mode, and you have to find correct call to SetPowerRequrement. But; if your code is stopped, then your device is sleeping, and you have missed Unattended mode.

I hope that will help a bit....
 

graememk

Member
Apr 18, 2008
21
0
Hi, been a member for a while and don't remember if i posted yet or not, I was coming up against this problem when developing a GPS application on a HTC TYTN2,

I wanted to constanty record the gps position, but not keep the screen on all the time,

I got around the sleep function of the device by not letting it into the suspend mode and keeping it in the unattended mode. this was done by calling:

PowerPolicyNotify(PPN_UNATTENDEDMODE, TRUE)
This put the lowest state the PPc could go into is the unattended mode but when it went into this mode the gps still turened off,

From reading an article on the code Project, : http://www.codeproject.com/KB/mobile/WiMoPower1.aspx i seen that different power levels ( i mean suspend etc here cant remember the poper term), turn off different applications and these are controlled via registry entries found here for the unatteneded mode :
HKEY_LOCAL_MACHINE\System\\CurrentControlSet\\Control\\Power\\State\\Unattended
the values that controls the GPS Intermediate Driver is "gpd0:" you change this to a 0 to keep GPS on in unatteneded mode, and 4 for it to be off in unattended mode,
I change it when my application starts and change it back when it finishes,
 

6ITdtvFQqY

Senior Member
Jul 31, 2008
59
0
The GPS is kept alive using the "gpd0:" name, not "gps0:".

So, when your application starts call (C#):

public const int PPN_UNATTENDEDMODE = 0x0003;
public const int POWER_NAME = 0x00000001;
public const int POWER_FORCE = 0x00001000;

PowerPolicyNotify( PPN_UNATTENDEDMODE, 1 ); // For app.
IntPtr GpsPowerHandle = SetPowerRequirement( "gpd0:", PowerState.FULL /* 0 */, POWER_NAME | POWER_FORCE, IntPtr.Zero, 0 ); // For GPS.


When your application stops call:

ReleasePowerRequirement( GpsPowerHandle );
PowerPolicyNotify( PPN_UNATTENDEDMODE, 0 );



Nothing else is necessary. Works on my Polaris.

In the attached app, you need to set "MainForm.KeepGpsAlive = true"and "MainForm.LogGps = true" to see this logged in "\Application Data\GpsLoc".

(You can use the compiled exe but without keep alive and logging. It can be used to send the position through SMS and sync the time.)


George
 

Attachments

  • GpsLoc.zip
    94.8 KB · Views: 122

6ITdtvFQqY

Senior Member
Jul 31, 2008
59
0
This is an update of the code. The previous one was crashing sometimes because the GPS reported a (cached) solution but there were no satellites in the solution.

(The GPS stays alive so long as the application is running.)
 

Attachments

  • GpsLoc.zip
    232.2 KB · Views: 180

mligor

Member
Oct 24, 2006
8
0
Frankfurt am Main
it is possible that GPD0: works better then GPS0:

GPD is basically GPSID (GPS Intermediate Driver) - the one that use virtual COM port to connect to GPS driver and allow multiple applications to use GPS signal.

Also GPSOpenDevice open GPD not GPS, therefor it make sense to keep that driver alive, and it will (probably) keep real GPS driver ON.

Maybe that is a reason why my application didn't work 100% on my HTC diamond.... I'm going to try that :)
 

NuShrike

Senior Recognized Developer
Sep 18, 2007
1,128
69
it is possible that GPD0: works better then GPS0:
CamerAware Buddy uses GPD0 and works 100% on FUZE.

I use D1(one) state to keep power-drain at lowest possible. I don't use SystemIdleTimerReset(), yet.

For lowest possible power drain, it's best to go with a SiRFIII (or MK) chip-based external bluetooth puck. The Qualcomm GPSone is a huge, inefficient, power-drainer compared to BT+SiRFIII.
 
Last edited:

mligor

Member
Oct 24, 2006
8
0
Frankfurt am Main
I have tried and using GPSID works great.

basically to keep GPS signal alive there are two possibilities (depends what you need):

1) in case that you want to keep LCD ON

- inform OS that you need always D0 state for GPD0: (SetPowerRequirement)
- inform OS that your application needs Unattended mode (PowerPolicyNotify)
- register for PowerState notifications (RequestPowerNotifications)
- call SystemIdleTimerReset() often enough that LCD will not go OFF and/or device to go to sleep.

in this case when user Press Power button, your will get notification that device is going in Unattended mode, and you have to keep device alive with SystemIdleTimerReset() and to prevent never going in Sleep mode.

in this case user will be able to "switch off" device, but your application will continue running. You can also optimize application that in Unattended mode, nothing is updated on the screen, and less CPU to use (to save a bit battery)

2) in case that you do not want to keep LCD On all the time

- inform OS that you need always D0 state for GPD0: (SetPowerRequirement)
- inform OS that your application needs Unattended mode (PowerPolicyNotify)
- register for PowerState notifications (RequestPowerNotifications)
- but DO NOT call SystemIdleTimerReset() unless device is in Unattended mode

when user press Power button or device automatically switch off LCD after timeout, you will get notification about it and THEN call SystemIdleTimerReset to keep device alive. When device is again in ON mode, SystemIdleTimerReset should not be called.

This will ensure your application to work transparent, and it is perfect for some kind of GPS logger etc...


---
all this is very nice, and my GPS logger works perfect, BUT (arghhh!!) when I keep GPSID alive, power consumption is going to be very high (~150mA), and that is for my 900mAh battery a lot of power (max 6h)

What are your experience about power consumption of GPS? Can be that something else on my phone eat so much power or that is GPS chip?
 

6ITdtvFQqY

Senior Member
Jul 31, 2008
59
0
GpsLoc has been updated into a full application.

See "Astrolabe - SMS your GPS position" at http://forum.xda-developers.com/showthread.php?p=4037827

Tests showed that in auto power saving mode the battery (of a HTC Polaris, 1350 mAh) would be depleted in about 16 hours, if no GPS signal is available; if there is a GPS signal, the autonomy should be greatly increased (an informal test indicates more than twice the autonomy). Without power saving, the battery would be depleted in about 6 hours.


(Using GPS0 didn't keep the GPS on when my PDA was in standby mode. GPD0 did.)
 
Last edited:

Top Liked Posts

  • There are no posts matching your filters.
  • 1
    I'm not sure if anyone has posted this but here we go anyways.

    I had issues keeping GPS enabled when I'd put my Kaiser into suspend mode and found a fix. Just change the value for each of these registry keys to "1". Or just download the CAB I whipped up.
    Code:
    HKLM\System\CurrentControlSet\Control\State\Resuming\gpd0:
    HKLM\System\CurrentControlSet\Control\State\Unattended\gpd0:
    HKLM\System\CurrentControlSet\Control\State\Suspend\gpd0:
    I believe this is a universal Windows Mobile fix and should work on any phone with a GPS chip. Don't quote me on that!!
Our Apps
Get our official app!
The best way to access XDA on your phone
Nav Gestures
Add swipe gestures to any Android
One Handed Mode
Eases uses one hand with your phone