none
Wake up device from suspend mode and restore connection RRS feed

  • Question

  • I would appreciate your assistance with the following issue.

     

    We have a problem with restoration of network interfaces on mobile devices when trying to wake up a device from the suspend mode.

     

    OS: Windows Mobile 5.0, Windows Mobile 6.0

    Devices: HP iPaq 114, HTC TyTNII

     In brief the problem looks like the following:

     The m obile devices have been configured to switch to  suspend mode when device is idle. We have developed a program, which periodically connects to a web service and polls for updates. Therefore, if the mobile device is in a suspend mode , the program also suspends and does not poll the web service.

    The challenge we tried to overcome was to wake up the device, fire up a network interface and restore connection to the Web service, poll it for updates and return to suspend mode if there is no news on the Web service. Only the network interface which provides Internet connection must be awaken on the mobile device in order to save power.

    We have developed a test program but i t is very unstable: devices hang often when the program tries to restore network interfaces.

    I would highly appreciate if you c ould point out what is wrong and how to wake up device and restore connection correctly? Please see the corresponding code below.

     

    int
     main()
    {
    LogMessage(TEXT("Starting..." ));
    MessageBox(NULL, _T("Press OK to start test." ),
    _T("Test wake up application." ), MB_OK);

    HANDLE l_hEvent = CreateEvent(NULL, FALSE, FALSE, _T("TestWakeUpEvent" ));
    if (l_hEvent == NULL)
    {
    MessageBox(NULL, _T("Event creation has failed." ),
    _T("Test wake up application." ), MB_OK);
    return -1;
    }

    SYSTEMTIME l_stTime;
    GetLocalTime(&l_stTime);
    FILETIME l_ftPlannedTime;
    SystemTimeToFileTime(&l_stTime, &l_ftPlannedTime);
    ULARGE_INTEGER l_bigInteger;
    l_bigInteger.LowPart = l_ftPlannedTime.dwLowDateTime;
    l_bigInteger.HighPart = l_ftPlannedTime.dwHighDateTime;
    l_bigInteger.QuadPart += 600000000; // 120 seconds

    l_ftPlannedTime.dwLowDateTime = l_bigInteger.LowPart;
    l_ftPlannedTime.dwHighDateTime = l_bigInteger.HighPart;
    FileTimeToSystemTime(&l_ftPlannedTime, &l_stTime);

    LogMessage(TEXT("Initiating wake up procedure..." ));
    BOOL l_bInitialized = CeRunAppAtTime(_T("\\\\.\\Notifications\\NamedEvents\\TestWakeUpEvent" ), &l_stTime);

    LogMessage(TEXT("Waiting for the event..." ));
    WaitForSingleObject(l_hEvent, INFINITE);

    CEDEVICE_POWER_STATE l_PowerState = D4;
    GetDevicePower(L"NDS0:" , POWER_NAME, &l_PowerState);
    _stprintf(l_szMessage, TEXT("NDS0: device power state is %d" ), l_PowerState);
    LogMessage(l_szMessage);

    LogMessage(TEXT("Go to unattended mode..." ));
    BOOL l_bUnatt = PowerPolicyNotify(PPN_UNATTENDEDMODE,TRUE);

    LogMessage(TEXT("Set power requirement..." ));
    HANDLE l_hPower0 = MySetPowerRequirement(L"BKL1:" , D0);
    HANDLE l_hPower2 = MySetPowerRequirement(L"\\NDS0:" , D0);
    HANDLE l_hPower1 = MySetPowerRequirement(L"\\UFN1:" , D0);

    LogMessage(TEXT("Initiating network waiting event..." ));
    CeRunAppAtEvent(_T("\\\\.\\Notifications\\NamedEvents\\TestWakeUpEvent" ), NOTIFICATION_EVENT_NET_CONNECT);

    LogMessage(TEXT("Waiting on network..." ));
    DWORD dwWait = WaitForSingleObject(l_hEvent, 20000);
    LogMessage(TEXT("Result of waiting on network..." ));
    if (dwWait == WAIT_OBJECT_0)
    {
    LogMessage(TEXT("Network has been initialized successfully..." ));
    }
    else
    {
    LogMessage(TEXT("Network initialization has failed..." ));
    }

    LogMessage(TEXT("Testing connection..." ));

    // Make some connection here

    BOOL l_bSuccess = TestConnection();

    LogMessage(TEXT("Releasing the power requirements..." ));
    ReleasePowerRequirement(l_hPower2);
    ReleasePowerRequirement(l_hPower1);
    ReleasePowerRequirement(l_hPower0);

    LogMessage(TEXT("Exiting from unattended mode..." ));
    PowerPolicyNotify(PPN_UNATTENDEDMODE,FALSE);

    LogMessage(TEXT("Closing the event handle..." ));
    CloseHandle(l_hEvent);

    MessageBox(NULL, TEXT("Test completed." ), TEXT("TestMobile.exe" ), MB_OK);

    return 0;
    }

    HANDLE MySetPowerRequirement(PVOID pDevice, CEDEVICE_POWER_STATE state)
    {
    HANDLE l_hPower = SetPowerRequirement(pDevice, state, POWER_NAME | POWER_FORCE, NULL, 0);
    if (l_hPower == NULL)
    {
    TCHAR l_szMessage[256];
    DWORD l_dwError = GetLastError();
    _stprintf(l_szMessage, TEXT("Unable to set power requirements for %s." ), pDevice);
    LogMessage(l_szMessage);
    _stprintf(l_szMessage, TEXT("Error code is: 0x%08X" ), l_dwError);
    LogMessage(l_szMessage);
    }
    return l_hPower;
    }


    Aleksey
    • Edited by _Aleksey_ Thursday, June 10, 2010 11:05 AM MySetPowerRequirement function added
    Thursday, June 10, 2010 5:59 AM

Answers

  • Well, I not going to attempt guess everything that could go wrong with the code above. However, when the scheduled connection is available connection manager will call the application you specified with the command line you specified; this is meant to allow the scheduled application to determine when it is being run as a result of connection manager and when it is being run for some other reason. The way I tested this was to have a command line that indicated that a connection was supposed to be available (which connection manger would pass) and doing the connection scheduling / cancellation from a separate invocation of the process.

    Right now, presuming the code above is running in \temp\mobile.exe, you have no way to detect whether the application is supposed to schedule the connection, cancel the connection, or use the connection.

    The bigger issue is that the API works in absolute time, rather than relative time. You need to do the appropraite calls to determine the current system time and then add the desired offsets when scheduling the connection.

    Cheers,

    -JL

    PS, I believe connection manager puts the system into unattended mode, so you should not necessarily expect to have access to the GUI when the scheduled connection becomes available.

    Friday, June 11, 2010 5:56 PM

All replies

  • Have you tried just scheduling something with Connection Manager instead? Connection Manager should manage the device power state transitions for you. I have written a bit of test code to Connection Manager. However, I have never needed to ship anything base on it so I can's comment on the issues you may encounter. My test did run for 2-3 days waking the device up and downloading a web page every 10 minutes.

    You would be using the function ConnMgrRegisterScheduledConnection.

    -JL

    Thursday, June 10, 2010 6:12 PM
  • I have tried to use Connection Manager (see code below). Probably, something is wrong in the code, but Pocket PC (HP iPAQ 114) does not wake up at all.

    Could you please point me what is wrong? Do I understand correct, that devide is full powered on, when Connection Manager wakes it up?

      MessageBox(NULL, TEXT("Press OK to begin."), TEXT("Starting..."), MB_OK);
    
      LogMessage("Checking if Connection Manager is ready...");
      // Make sure Connection Manager is ready
      HANDLE hConnMgr = NULL;
      BOOL bAvailable = FALSE;
      hConnMgr = ConnMgrApiReadyEvent();
    
      if(!hConnMgr)
      {
       LogMessage("Connection Manager is not ready.");
       return FALSE;
      }
    
      // Wait for 1 second to see if Connection Manager has
      // signaled the event
      DWORD dwResult = WaitForSingleObject(hConnMgr, 1000);
    
      if(dwResult == WAIT_OBJECT_0)
       bAvailable = TRUE;
    
      // Close the event handle
      if(hConnMgr)
       CloseHandle(hConnMgr);
    
      // Did it connect ok?
      if(!bAvailable)
      {
       LogMessage("Connection Manager is not ready.");
       return FALSE;
      }
    
      GUID guidNetworkObject;
      DWORD dwIndex = 0;
      TCHAR tchRemoteUrl[256] = TEXT("\0");
      wsprintf(tchRemoteUrl, TEXT("http://aleksey"));
    
      LogMessage("Mapping the URL to destination network...");
      if(ConnMgrMapURL(tchRemoteUrl, &guidNetworkObject, &dwIndex)
       == E_FAIL)
      {
       LogMessage("Could not map the request to a network identifier");
       return  -1;
      }
    
      if(SUCCEEDED(ConnMgrUnregisterScheduledConnection(TEXT("TestToken"))))
      {
       LogMessage("Scheduled event has been cancelled.");
      }
    
      LogMessage("Scheduling the connection...");
    
      SYSTEMTIME l_stTime;
      GetLocalTime(&l_stTime);
      FILETIME  l_ftPlannedTime;
      SystemTimeToFileTime(&l_stTime, &l_ftPlannedTime);
      ULARGE_INTEGER l_bigInteger;
      l_bigInteger.LowPart  = l_ftPlannedTime.dwLowDateTime;
      l_bigInteger.HighPart  = l_ftPlannedTime.dwHighDateTime;
    
      // Set up the schedule times
      // In 15 seconds, let's try every 1 minute for 10 minutes
      DWORD dwSecStart = 15;
      DWORD dwSecDuration = 600;
      DWORD dwSecPeriod = 60;
    
      // Schedule a connection
      SCHEDULEDCONNECTIONINFO sci;
    
      memset(&sci, 0, sizeof(SCHEDULEDCONNECTIONINFO));
    
      sci.guidDest = guidNetworkObject;
      sci.uiStartTime =
       l_bigInteger.QuadPart+(UINT64)(10000000)*(UINT64)dwSecStart;
      sci.uiEndTime = l_bigInteger.QuadPart+(UINT64)(10000000)*
       (UINT64)(dwSecStart+dwSecDuration);
      sci.uiPeriod = (UINT64)(10000000)*(UINT64)(dwSecPeriod);
      sci.bPiggyback = TRUE;
    
      _tcscpy(sci.szAppName, _T("\\Temp\\Mobile.exe"));
      _tcscpy(sci.szCmdLine, _T("\\Temp\\Mobile.exe"));
      _tcscpy(sci.szToken, TEXT("TestToken"));
    
      HRESULT hr = ConnMgrRegisterScheduledConnection(&sci);
      if(FAILED(hr))
      {
       LogMessage("Could not schedule the connection event");
       return FALSE;
      }
    
      LogMessage("Sleeping while testing...");
      Sleep(650000);
    
      LogMessage("Canceling the scheduled event...");
      if(SUCCEEDED(ConnMgrUnregisterScheduledConnection(TEXT("TestToken"))))
      {
       LogMessage("Scheduled event has been cancelled.");
      }
    
      MessageBox(NULL, TEXT("Completed."), TEXT("Finishing..."), MB_OK);
      LogMessage("Completed.");
    Thank you for your help.


    Aleksey
    Friday, June 11, 2010 11:58 AM
  • Well, I not going to attempt guess everything that could go wrong with the code above. However, when the scheduled connection is available connection manager will call the application you specified with the command line you specified; this is meant to allow the scheduled application to determine when it is being run as a result of connection manager and when it is being run for some other reason. The way I tested this was to have a command line that indicated that a connection was supposed to be available (which connection manger would pass) and doing the connection scheduling / cancellation from a separate invocation of the process.

    Right now, presuming the code above is running in \temp\mobile.exe, you have no way to detect whether the application is supposed to schedule the connection, cancel the connection, or use the connection.

    The bigger issue is that the API works in absolute time, rather than relative time. You need to do the appropraite calls to determine the current system time and then add the desired offsets when scheduling the connection.

    Cheers,

    -JL

    PS, I believe connection manager puts the system into unattended mode, so you should not necessarily expect to have access to the GUI when the scheduled connection becomes available.

    Friday, June 11, 2010 5:56 PM