📄 pwstates.cpp
字号:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// Use of this sample source code is subject to the terms of the Microsoft
// license agreement under which you licensed this sample source code. If
// you did not accept the terms of the license agreement, you are not
// authorized to use this sample source code. For the terms of the license,
// please see the license agreement between you and Microsoft or, if applicable,
// see the LICENSE.RTF on your install media or the root of your tools installation.
// THE SAMPLE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES.
//
//
// This module implements a set of states defined by the MS Mobile Devices
// Division as a baseline for Pocket PC devices. OEMs may choose to customize
// this file to support the hardware specific to their platform.
//
#include <pmimpl.h>
#include <nkintr.h>
#include <extfile.h>
#include <pmpolicy.h>
#include <Csync.h>
#include <cRegEdit.h>
#include <pwsdef.h>
typedef enum {
NoTimeoutItem,
SuspendTimeout,
SystemActivityTimeout,
UserActivityTimeout,
} TIMEOUT_ITEM, *PTIMEOUT_ITEM;
typedef enum {
On, // system is running normally with UI enabled
UserIdle, // User Idle state.
SystemIdle,
Resuming, // system is determining what to do after a resume
Suspend, // system suspended, all devices off (or wake-enabled)
ColdReboot,
Reboot,
UnknownState = PM_UNKNOWN_POWER_STATE, // Unknown
} PLATFORM_ACTIVITY_STATE, *PPLATFORM_ACTIVITY_STATE;
#define STRING_ON _T("on")
#define STRING_USERIDLE _T("useridle")
#define STRING_SYSTEMIDLE _T("systemidle")
#define STRING_RESUMING _T("resuming")
#define STRING_SUSPEND _T("suspend")
#define STRING_ColdReboot _T("coldreboot")
#define STRING_Reboot _T("reboot")
// platform-specific default values
#define DEF_TIMEOUTTOUSERIDLE 60 // in seconds, 0 to disable
#define DEF_TIMEOUTTOSYSTEMIDLE 300 // in seconds, 0 to disable
#define DEF_TIMEOUTTOSUSPEND 600 // in seconds, 0 to disable
extern DWORD RegReadStateTimeout(HKEY hk, LPCTSTR pszName, DWORD dwDefault);
// need "C" linkage for compatibility with C language PDD implementations
extern "C" extern POWER_BROADCAST_POWER_INFO gSystemPowerStatus;
class PowerStateManager: public DefaultPowerStateManager {
public:
PowerStateManager(PVOID pParam)
: DefaultPowerStateManager (pParam)
{
m_fActiveManagement = TRUE;
}
~PowerStateManager() {
while (m_pPowerStateList!=NULL) {
PowerState * pNextState = m_pPowerStateList->GetNextPowerState();
delete m_pPowerStateList;
m_pPowerStateList = pNextState;
}
}
BOOL Init() {
if (DefaultPowerStateManager::Init() && m_pSystemActivity && m_pUserActivity) { // This is required by Default PM.
PlatformLoadTimeouts();
ReInitTimeOuts();
return CreatePowerStateList();
}
return FALSE;
}
virtual void ResetUserIdleTimeout(BOOL fIdle) {
m_dwCurUserIdleTimeout = (fIdle? GetUserIdleTimeOut():INFINITE);
if (m_dwCurUserIdleTimeout == 0 )
m_dwCurUserIdleTimeout = INFINITE ;
m_dwCurTimeoutToSystemIdle = (fIdle? GetSystemIdleTimeOut(): INFINITE);
if (m_dwCurTimeoutToSystemIdle == 0)
m_dwCurTimeoutToSystemIdle = INFINITE ;
}
virtual void ResetSystemIdleTimeTimeout(BOOL fIdle) {
m_dwCurSuspendTimeout = (fIdle? GetSuspendTimeOut(): INFINITE);
if (m_dwCurSuspendTimeout == 0)
m_dwCurSuspendTimeout = INFINITE ;
}
virtual void SubtractTimeout(DWORD dwTicks) {
if (m_dwCurSuspendTimeout != INFINITE )
m_dwCurSuspendTimeout = (m_dwCurSuspendTimeout>dwTicks? m_dwCurSuspendTimeout- dwTicks: 0 );
if (m_dwCurTimeoutToSystemIdle != INFINITE)
m_dwCurTimeoutToSystemIdle = (m_dwCurTimeoutToSystemIdle>dwTicks? m_dwCurTimeoutToSystemIdle- dwTicks: 0 );
if (m_dwCurUserIdleTimeout!= INFINITE)
m_dwCurUserIdleTimeout = (m_dwCurUserIdleTimeout> dwTicks? m_dwCurUserIdleTimeout - dwTicks: 0 );
}
virtual DWORD ThreadRun() {
SETFNAME(_T("PowerStateManager::ThreadRun"));
// Assume First state is PowerStateOn. So please put POwerStateOn on the header.
if (m_pPowerStateList) {
// We need get first SetSystemPower from device to make initial power state correct.
PowerState * pCurPowerState = GetFirstPowerState();
if (pCurPowerState != NULL) {
Lock();
m_pCurPowerState = pCurPowerState;
pCurPowerState->EnterState();
BOOL fDone = FALSE;
// Create Legacy Registry modify notification event array.
while (!fDone && pCurPowerState) {
PLATFORM_ACTIVITY_STATE curState = (PLATFORM_ACTIVITY_STATE) pCurPowerState->GetState();
PLATFORM_ACTIVITY_STATE newState = curState;
Unlock();
PLATFORM_ACTIVITY_EVENT activityEvent = pCurPowerState->WaitForEvent(INFINITE,0 ,NULL);
PMLOGMSG(ZONE_PLATFORM, (_T("%s: activityEvent = %d \r\n" ), pszFname,activityEvent)) ;
Lock();
if (pCurPowerState != m_pCurPowerState) {
if (activityEvent!= SystemPowerStateAPI) {
PMLOGMSG(ZONE_ERROR|| ZONE_PLATFORM,(_T("Multiple Event happens during SentSystemPowerState %d, Event will evaluated in new state \r\n"),newState));
}
pCurPowerState = m_pCurPowerState;
newState = curState = (PLATFORM_ACTIVITY_STATE) pCurPowerState->GetState();
PMLOGMSG(ZONE_PLATFORM, (_T("%s: Jack newState = %d [pCurPowerState != m_pCurPowerState]\r\n" ), pszFname, newState));
if ((PLATFORM_ACTIVITY_STATE) pCurPowerState->GetState() == Resuming
|| (PLATFORM_ACTIVITY_STATE)pCurPowerState->GetState() == Suspend) {
// Application call SetSystemPowerState set to Resuming or Suspend in other thread.
// This thread come back, calculate time elapsed and update it. So timeout is wrong
// we need re-intialize timeout paramenter
ReInitTimeOuts( ) ;
}
}
switch (activityEvent) {
case PmShutDown :
fDone = TRUE;
break;
case PmReloadActivityTimeouts:
PlatformLoadTimeouts(); // No break we need run ReInitTimeouts.
case RestartTimeouts:
case PowerSourceChange:
case SystemPowerStateChange:
case PowerButtonPressed:
case AppButtonPressed:
ReInitTimeOuts();
pCurPowerState->DefaultEventHandle( activityEvent ) ;
break;
case SystemPowerStateAPI:
break;
default:
PMLOGMSG(ZONE_PLATFORM, (_T("%s: Jack default case\r\n")));
pCurPowerState->DefaultEventHandle( activityEvent ) ;
break;
}
pCurPowerState = SetSystemState(pCurPowerState ) ;
ASSERT(pCurPowerState!=NULL);
m_pCurPowerState = pCurPowerState; // Update current state.
}
Unlock();
}
else
ASSERT(FALSE);
}
return 0;
}
virtual void ReAdjustTimeOuts( ) {
if (m_dwCurSuspendTimeout > GetSuspendTimeOut() ) {
if ((m_dwCurSuspendTimeout=GetSuspendTimeOut()) == 0 )
m_dwCurSuspendTimeout = INFINITE ;
}
if (m_dwCurTimeoutToSystemIdle > GetSystemIdleTimeOut() ) {
if ((m_dwCurTimeoutToSystemIdle=GetSystemIdleTimeOut()) == 0 )
m_dwCurTimeoutToSystemIdle = INFINITE ;
}
if (m_dwCurUserIdleTimeout > GetUserIdleTimeOut() ) {
if ((m_dwCurUserIdleTimeout=GetUserIdleTimeOut()) == 0)
m_dwCurUserIdleTimeout = INFINITE ;
}
}
virtual DWORD GetSmallestTimeout(PTIMEOUT_ITEM pTimeoutItem) {
DWORD dwReturn = INFINITE;
TIMEOUT_ITEM activeEvent = NoTimeoutItem;
if (dwReturn > m_dwCurSuspendTimeout) {
dwReturn = m_dwCurSuspendTimeout;
activeEvent = SuspendTimeout ;
}
if (dwReturn > m_dwCurTimeoutToSystemIdle) {
dwReturn = m_dwCurTimeoutToSystemIdle;
activeEvent = SystemActivityTimeout ;
}
if (dwReturn > m_dwCurUserIdleTimeout ) {
dwReturn = m_dwCurUserIdleTimeout;
activeEvent = UserActivityTimeout;
}
if (pTimeoutItem) {
*pTimeoutItem = activeEvent;
}
return dwReturn;
}
void DisableUserIdleTimeout() { m_dwCurUserIdleTimeout = INFINITE; };
void DisableSuspendTimeout() { m_dwCurSuspendTimeout = INFINITE; };
void DisableSystemIdleTimeout() { m_dwCurTimeoutToSystemIdle = INFINITE; };
// Timer Function.
virtual void ReInitTimeOuts() {
m_dwCurSuspendTimeout = GetSuspendTimeOut();
m_dwCurTimeoutToSystemIdle = GetSystemIdleTimeOut();
m_dwCurUserIdleTimeout = GetUserIdleTimeOut() ;
// If timer is not set. It is not supported.
if (m_dwCurUserIdleTimeout == 0 )
m_dwCurUserIdleTimeout = INFINITE ;
if (m_dwCurTimeoutToSystemIdle == 0)
m_dwCurTimeoutToSystemIdle = INFINITE ;
if (m_dwCurSuspendTimeout == 0)
m_dwCurSuspendTimeout = INFINITE ;
}
virtual void PlatformResumeSystem(BOOL fSuspened) {
SETFNAME(_T("PowerStateManager::PlatformResumeSystem"));
TCHAR szResumeState[MAX_PATH];
DWORD dwStatus;
HANDLE hevActivityReset = NULL;
PMLOGMSG(ZONE_RESUME, (_T("+%s: suspend flag is %d\r\n"), pszFname, fSuspened));
// Was this an unexpected resume event? If so, there may be a thread priority problem
// or some piece of software suspended the system without calling SetSystemPowerState().
DEBUGCHK(fSuspened);
if(!fSuspened) {
// Unexpected resume -- turn everything back on. OEMs may choose to customize this
// routine to dynamically determine which system power state is most appropriate rather
// than using PlatformMapPowerStateHint().
PMLOGMSG(ZONE_WARN || ZONE_RESUME, (_T("%s: WARNING: unexpected resume!\r\n"), pszFname));
dwStatus = PlatformMapPowerStateHint(POWER_STATE_ON, szResumeState, dim(szResumeState));
DEBUGCHK(dwStatus == ERROR_SUCCESS);
// Go into the new state. OEMs that choose to support unexpected resumes may want to
// lock PM variables with PMLOCK(), then set the curDx and actualDx values for all
// devices to PwrDeviceUnspecified before calling PmSetSystemPowerState_I(). This will
// force an update IOCTL to all devices.
dwStatus = PmSetSystemPowerState_I(szResumeState, 0, POWER_FORCE, TRUE);
DEBUGCHK(dwStatus == ERROR_SUCCESS);
} else if(m_fActiveManagement) {
DWORD dwWakeSource, dwBytesReturned;
BOOL fOk;
// get the system wake source to help determine which power state we resume into
fOk = KernelIoControl(IOCTL_HAL_GET_WAKE_SOURCE, NULL, 0, &dwWakeSource,
sizeof(dwWakeSource), &dwBytesReturned);
if(fOk) {
// ioctl succeeded (not all platforms necessarily support it), but sanity check
// the return value, just in case.
if(dwBytesReturned != sizeof(dwWakeSource)) {
PMLOGMSG(ZONE_WARN, (_T("%s: KernelIoControl() returned an invalid size %d\r\n"),
pszFname, dwBytesReturned));
} else {
// look for an activity timer corresponding to this wake source
PACTIVITY_TIMER pat = ActivityTimerFindByWakeSource(dwWakeSource);
if(pat != NULL) {
PMLOGMSG(ZONE_RESUME || ZONE_TIMERS, (_T("%s: signaling '%s' activity at resume\r\n"),
pszFname, pat->pszName));
hevActivityReset = pat->hevReset;
}
}
}
// did we find an activity timer?
if(hevActivityReset == NULL) {
PMLOGMSG(ZONE_RESUME, (_T("%s: assuming user activity\r\n"), pszFname));
hevActivityReset = (m_pUserActivity!=NULL ?m_pUserActivity->hevReset: NULL);
}
}
// is there an activity timer we need to reset?
if(hevActivityReset != NULL) {
// found a timer, elevate the timer management priority thread so that it
// executes before the suspending thread
DWORD dwOldPriority = CeGetThreadPriority(ghtActivityTimers);
DWORD dwNewPriority = (CeGetThreadPriority(GetCurrentThread()) - 1);
DEBUGCHK(dwNewPriority >= 0);
SetEvent(hevActivityReset);
CeSetThreadPriority(ghtActivityTimers, dwNewPriority);
CeSetThreadPriority(ghtActivityTimers, dwOldPriority);
}
PMLOGMSG(ZONE_RESUME, (_T("-%s\r\n"), pszFname));
}
protected:
virtual void PlatformLoadTimeouts() {
DWORD dwStatus;
TCHAR szPath[MAX_PATH];
HKEY hk;
SETFNAME(_T("PowerStateManager::PlatformLoadTimeouts"));
// assume default values
m_dwACSuspendTimeout = DEF_TIMEOUTTOSUSPEND * 1000;
m_dwACTimeoutToSystemIdle = DEF_TIMEOUTTOSYSTEMIDLE * 1000 ;
m_dwACUserIdleTimeout = DEF_TIMEOUTTOUSERIDLE * 1000;
m_dwBattSuspendTimeout = DEF_TIMEOUTTOSUSPEND * 1000;
m_dwBattTimeoutToSystemIdle = DEF_TIMEOUTTOSYSTEMIDLE * 1000 ;
m_dwBattUserIdleTimeout = DEF_TIMEOUTTOUSERIDLE * 1000;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -