📄 platform.cpp
字号:
pOldCeilingDx = pdpr;
}
PMLOCK();
if ( fPasswordOn != gfPasswordOn ) {
if (gfGwesReady && gpfnShowStartupWindow && fPasswordOn )
gpfnShowStartupWindow();
gfPasswordOn = fPasswordOn;
}
PMUNLOCK();
// are we suspending?
if(fSuspendSystem) {
// clear activity flags
ResetEvent(ghevUserActive);
ResetEvent(ghevSignalUserActivity);
ResetEvent(ghevSystemActive);
ResetEvent(ghevSignalSystemActivity);
// set a flag to notify the resume thread that this was a controlled
// suspend
gfSystemSuspended = TRUE;
PMLOGMSG(ZONE_PLATFORM || ZONE_RESUME, (_T("%s: calling PowerOffSystem()\r\n"), pszFname));
PowerOffSystem(); // sets a flag in the kernel for the scheduler
Sleep(0); // so we force the scheduler to run
PMLOGMSG(ZONE_PLATFORM || ZONE_RESUME, (_T("%s: back from PowerOffSystem()\r\n"), pszFname));
// clear the suspend flag
gfSystemSuspended = FALSE;
// resume into an appropriate system power state
if(gfActiveManagement) {
// figure out the right power state
PlatformUpdateSystemPowerState(Resume, INFINITE);
// For now, synchronize with the system management thread by reloading timeouts.
// We can't just have the system thread enter the resume state because
// FileSystemPowerFunction(FSNOTIFY_POWER_OFF) blocks all other threads from
// accessing the registry.
SetEvent(ghevReloadActivityTimeouts);
} else {
// resume into a default system power state
LPTSTR pszResumeState = _T("on");
PMLOGMSG(ZONE_RESUME, (_T("%s: resuming into '%s' system power state\r\n"),
pszFname, pszResumeState));
dwStatus = PmSetSystemPowerState_I(pszResumeState, 0, POWER_FORCE, TRUE);
DEBUGCHK(dwStatus == ERROR_SUCCESS);
}
// tell gwes to wake up
if(gpfnGwesPowerUp != NULL && gfGwesReady) {
gpfnGwesPowerUp(fWantStartupScreen);
}
// send out resume notification
pbb.Message = PBT_RESUME;
pbb.Flags = 0;
pbb.Length = 0;
pbb.SystemPowerState[0] = 0;
GenerateNotifications((PPOWER_BROADCAST) &pbb);
}
} else {
// release the unused new state information
SystemPowerStateDestroy(pNewSystemPowerState);
while(pNewCeilingDx != NULL) {
PDEVICE_POWER_RESTRICTION pdpr = pNewCeilingDx->pNext;
PowerRestrictionDestroy(pNewCeilingDx);
pNewCeilingDx = pdpr;
}
}
}
// restore our priority if we updated it during a suspend transition
if(giSuspendPriority != 0 && iPreSuspendPriority != 0) {
PMLOGMSG(ZONE_PLATFORM, (_T("%s: restoring thread priority to %d\r\n"),
pszFname, iPreSuspendPriority));
CeSetThreadPriority(GetCurrentThread(), iPreSuspendPriority);
}
// if we're initializing, tell the management thread we're done
if(fFirstCall) {
if(ghevReloadActivityTimeouts != NULL) SetEvent(ghevReloadActivityTimeouts);
fFirstCall = FALSE;
}
return dwStatus;
}
// This routine reads a power state timeout value from the registry. The
// timeout value should be expressed in seconds; this routine returns
// the timeout value in milliseconds.
DWORD
RegReadStateTimeout(HKEY hk, LPCTSTR pszName, DWORD dwDefault)
{
DWORD dwValue, dwSize, dwStatus;
dwSize = sizeof(dwValue);
dwStatus = RegQueryTypedValue(hk, pszName, &dwValue, &dwSize, REG_DWORD);
if(dwStatus != ERROR_SUCCESS) {
dwValue = dwDefault;
} else {
if(dwValue == 0) {
dwValue = INFINITE;
} else {
if(dwValue > MAXACTIVITYTIMEOUT) {
dwValue = MAXACTIVITYTIMEOUT;
}
}
}
// convert to milliseconds
if(dwValue != INFINITE) {
dwValue *= 1000;
}
return dwValue;
}
// This routine reads the system's timeout values from the registry. It
// is called at boot time and whenever the reload event is signaled.
VOID
PlatformLoadTimeouts(VOID)
{
DWORD dwStatus;
TCHAR szPath[MAX_PATH];
HKEY hk;
SETFNAME(_T("PlatformLoadTimeouts"));
// assume default values
gdwACTimeoutToUserIdle = DEF_TIMEOUTTOUSERIDLE * 1000;
gdwACTimeoutToSystemIdle = DEF_TIMEOUTTOSYSTEMIDLE * 1000;
gdwACTimeoutToSuspend = DEF_TIMEOUTTOSUSPEND * 1000;
gdwBattTimeoutToUserIdle = DEF_TIMEOUTTOUSERIDLE * 1000;
gdwBattTimeoutToSystemIdle = DEF_TIMEOUTTOSYSTEMIDLE * 1000;
gdwBattTimeoutToSuspend = DEF_TIMEOUTTOSUSPEND * 1000;
// get timeout thresholds for transitions between states
wsprintf(szPath, _T("%s\\%s"), PWRMGR_REG_KEY, _T("Timeouts"));
dwStatus = RegOpenKeyEx(HKEY_LOCAL_MACHINE, szPath, 0, 0, &hk);
if(dwStatus == ERROR_SUCCESS) {
// read system power state timeouts
gdwACTimeoutToUserIdle = RegReadStateTimeout(hk, _T("ACUserIdle"), DEF_TIMEOUTTOUSERIDLE);
gdwACTimeoutToSystemIdle = RegReadStateTimeout(hk, _T("ACSystemIdle"), DEF_TIMEOUTTOSYSTEMIDLE);
gdwACTimeoutToSuspend = RegReadStateTimeout(hk, _T("ACSuspend"), DEF_TIMEOUTTOSUSPEND);
gdwBattTimeoutToUserIdle = RegReadStateTimeout(hk, _T("BattUserIdle"), DEF_TIMEOUTTOUSERIDLE);
gdwBattTimeoutToSystemIdle = RegReadStateTimeout(hk, _T("BattSystemIdle"), DEF_TIMEOUTTOSYSTEMIDLE);
gdwBattTimeoutToSuspend = RegReadStateTimeout(hk, _T("BattSuspend"), DEF_TIMEOUTTOSUSPEND);
// release resources
RegCloseKey(hk);
}
PMLOGMSG(ZONE_INIT || ZONE_PLATFORM,
(_T("%s: ACUserIdle %d, ACSystemIdle %d, ACSuspend %d, BattUserIdle %d, BattSystemIdle %d, BattSuspend %d\r\n"),
pszFname, gdwACTimeoutToUserIdle, gdwACTimeoutToSystemIdle, gdwACTimeoutToSuspend,
gdwBattTimeoutToUserIdle, gdwBattTimeoutToSystemIdle, gdwBattTimeoutToSuspend));
}
// This routine determines if the PM is supposed to be actively managing power on the
// system or not. If it isn't, then the code that updates our internal state machine
// based on system activity is extraneous and can be removed by the OEM.
BOOL
PlatformPMActivelyManagesPower(void)
{
BOOL fActivelyManaging = FALSE;
TCHAR szPath[MAX_PATH];
HKEY hk;
DWORD dwStatus;
SETFNAME(_T("PlatformPMActivelyManagesPower"));
// open the timeout registry key
wsprintf(szPath, _T("%s\\%s"), PWRMGR_REG_KEY, _T("Timeouts"));
dwStatus = RegOpenKeyEx(HKEY_LOCAL_MACHINE, szPath, 0, 0, &hk);
if(dwStatus == ERROR_SUCCESS) {
DWORD dwValue, dwType;
DWORD dwSize = sizeof(dwValue);
dwStatus = RegQueryValueEx(hk, _T("ACUserIdle"), NULL, &dwType, (LPBYTE) &dwValue, &dwSize);
if(dwStatus == ERROR_SUCCESS && dwType == REG_DWORD) {
fActivelyManaging = TRUE;
}
RegCloseKey(hk);
}
PMLOGMSG(ZONE_INIT || ZONE_PLATFORM, (_T("%s: returning %d\r\n"), pszFname, fActivelyManaging));
return fActivelyManaging;
}
// This routine implements the main power manager event loop. This loop implements
// the power manager's response to external events, such as being docked in a cradle,
// running low on battery power, going on or off AC power, etc. This sample implementation
// simply monitors battery level changes and generates the appropriate notifications.
EXTERN_C VOID WINAPI
PlatformManageSystemPower(HANDLE hevReady)
{
BOOL fDone = FALSE;
HANDLE hEvents[7], hqNotify = NULL;
DWORD dwTimeout, dwStatus, dwNumEvents;
HMODULE hmCoreDll = NULL;
PACTIVITY_TIMER pat;
SETFNAME(_T("PlatformManageSystemPower"));
PMLOGMSG(ZONE_INIT || ZONE_PLATFORM, (_T("+%s\r\n"), pszFname));
// init globals
ghevReloadActivityTimeouts = NULL;
ghevRestartTimers = NULL;
// determine thread priority settings while we're suspending (in case
// of priority inversion)
if(!GetPMThreadPriority(_T("PreSuspendPriority256"), &giPreSuspendPriority)) {
giPreSuspendPriority = DEF_PRESUSPEND_THREAD_PRIORITY;
}
if(!GetPMThreadPriority(_T("SuspendPriority256"), &giSuspendPriority)) {
giSuspendPriority = DEF_SUSPEND_THREAD_PRIORITY;
}
// get events from activity timers
PMLOCK();
pat = ActivityTimerFindByName(_T("UserActivity"));
if(pat != NULL) {
ghevSignalUserActivity = pat->hevReset;
ghevUserActive = pat->hevActive;
ghevUserInactive = pat->hevInactive;
} else {
ghevSignalUserActivity = NULL;
ghevUserActive = NULL;
ghevUserInactive = NULL;
}
pat = ActivityTimerFindByName(_T("SystemActivity"));
if(pat != NULL) {
ghevSignalSystemActivity = pat->hevReset;
ghevSystemActive = pat->hevActive;
ghevSystemInactive = pat->hevInactive;
} else {
ghevSignalSystemActivity = NULL;
ghevSystemActive = NULL;
ghevSystemInactive = NULL;
}
PMUNLOCK();
// determine if we're supposed to be actively managing power on this system
gfActiveManagement = PlatformPMActivelyManagesPower();
// Get pointers to GWES's suspend/routine APIs. These require GWES, so the OEM may
// not have them on this platform. Also get battery level APIs, which require a
// battery driver and may not be present.
hmCoreDll = (HMODULE) LoadLibrary(_T("coredll.dll"));
gfGwesReady = FALSE;
PmInitPowerStatus(hmCoreDll);
if(hmCoreDll != NULL) {
gpfnGwesPowerDown = (PFN_GwesPowerDown) GetProcAddress(hmCoreDll, _T("GwesPowerDown"));
gpfnGwesPowerUp = (PFN_GwesPowerUp) GetProcAddress(hmCoreDll, _T("GwesPowerUp"));
gpfnShowStartupWindow = (PFN_ShowStartupWindow) GetProcAddress(hmCoreDll, _T("ShowStartupWindow"));
// do we have both gwes suspend/resume APIs?
if(gpfnGwesPowerDown == NULL || gpfnGwesPowerUp == NULL) {
// no, ignore GWES
gpfnGwesPowerDown = NULL;
gpfnGwesPowerUp = NULL;
} else {
// monitor GWES apis
ghevGwesReady = OpenEvent(EVENT_ALL_ACCESS, FALSE, _T("SYSTEM/GweApiSetReady"));
DEBUGCHK(ghevGwesReady != NULL);
}
}
// are we using the PM in an active or passive role? For now, key off of the presence
// of the PM timeout value for AC power.
if(!gfActiveManagement) {
PMLOGMSG(ZONE_PLATFORM || ZONE_INIT, (_T("%s: PM role on platform is passive, exiting\r\n"),
pszFname));
// indicate we're ready, since there's no error involved in passive PM
SetEvent(hevReady);
Sleep(1000); // don't want PM initialization to fail when we exit
goto done;
}
// create events
ghevReloadActivityTimeouts = CreateEvent(NULL, FALSE, FALSE, _T("PowerManager/ReloadActivityTimeouts"));
ghevRestartTimers = CreateEvent(NULL, FALSE, FALSE, NULL);
if(ghevReloadActivityTimeouts == NULL
|| ghevRestartTimers == NULL) {
PMLOGMSG(ZONE_WARN, (_T("%s: CreateEvent() failed for system event\r\n"), pszFname));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -