VirtualBox

Changeset 15905 in vbox for trunk/src/VBox/Main


Ignore:
Timestamp:
Jan 13, 2009 9:26:39 AM (16 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
41526
Message:

Main-OSX: Trigger save state on power low event.

Location:
trunk/src/VBox/Main
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Main/darwin/HostPowerDarwin.cpp

    r14527 r15905  
    2424
    2525#include <IOKit/IOMessage.h>
     26#include <IOKit/ps/IOPowerSources.h>
     27#include <IOKit/ps/IOPSKeys.h>
     28
     29#define POWER_SOURCE_OUTLET 1
     30#define POWER_SOURCE_BATTERY 2
    2631
    2732HostPowerServiceDarwin::HostPowerServiceDarwin (VirtualBox *aVirtualBox)
    28   : HostPowerService (aVirtualBox),
    29     mThread (NULL),
    30     mRootPort (MACH_PORT_NULL),
    31     mNotifyPort (nil),
    32     mRunLoop (nil)
     33  : HostPowerService (aVirtualBox)
     34  , mThread (NULL)
     35  , mRootPort (MACH_PORT_NULL)
     36  , mNotifyPort (nil)
     37  , mRunLoop (nil)
     38  , mCritical (false)
    3339{
    3440    /* Create the new worker thread. */
     
    5763}
    5864
     65
    5966DECLCALLBACK(int) HostPowerServiceDarwin::powerChangeNotificationThread (RTTHREAD ThreadSelf, void *pInstance)
    6067{
    6168    HostPowerServiceDarwin *pPowerObj = static_cast<HostPowerServiceDarwin *> (pInstance);
    6269
    63 //    OSErr retCode = AEInstallEventHandler(kAEMacPowerMgtEvt, kAEMacLowPowerSaveData,
    64 //                                          HostPowerServiceDarwin::lowPowerEventHandler,
    65 //                                          pPowerObj, false);
     70    /* We have to initial set the critical state of the battery, cause we want
     71     * not the HostPowerService to inform about that state when a VM starts.
     72     * See lowPowerHandler for more info. */
     73    pPowerObj->checkBatteryCriticalLevel();
    6674
    6775    /* Register to receive system sleep notifications */
     
    7987                        IONotificationPortGetRunLoopSource (pPowerObj->mNotifyPort),
    8088                        kCFRunLoopCommonModes);
     89
     90    /* Register for all battery change events. The handler will check for low
     91     * power events themself. */
     92    CFRunLoopSourceRef runLoopSource = IOPSNotificationCreateRunLoopSource(HostPowerServiceDarwin::lowPowerHandler,
     93                                                                           pPowerObj);
     94    CFRunLoopAddSource(pPowerObj->mRunLoop,
     95                       runLoopSource,
     96                       kCFRunLoopCommonModes);
     97
    8198    /* Start the run loop. This blocks. */
    8299    CFRunLoopRun();
    83 
    84100    return VINF_SUCCESS;
    85101}
    86102
    87 void HostPowerServiceDarwin::powerChangeNotificationHandler (void *pData, io_service_t service, natural_t messageType, void *pMessageArgument)
    88 {
    89     HostPowerServiceDarwin *pPowerObj = static_cast<HostPowerServiceDarwin *> (pData);
    90 //    printf( "messageType %08lx, arg %08lx\n", (long unsigned int)messageType, (long unsigned int)pMessageArgument );
     103void HostPowerServiceDarwin::powerChangeNotificationHandler (void *pvData, io_service_t service, natural_t messageType, void *pMessageArgument)
     104{
     105    HostPowerServiceDarwin *pPowerObj = static_cast<HostPowerServiceDarwin *> (pvData);
     106    Log (( "powerChangeNotificationHandler: messageType %08lx, arg %08lx\n", (long unsigned int)messageType, (long unsigned int)pMessageArgument));
    91107
    92108    switch (messageType)
     
    132148}
    133149
    134 OSErr HostPowerServiceDarwin::lowPowerEventHandler (const AppleEvent *event, AppleEvent *replyEvent, long data)
    135 {
    136     printf ("low power event\n");
    137     LogRel (("low power event\n"));
    138 //    HostPowerServiceDarwin *pPowerObj = reinterpret_cast<HostPowerServiceDarwin *> (data);
    139 //    pPowerObj->notify(HostPowerEvent_BatteryLow);
    140     return noErr;
    141 }
    142 
     150void HostPowerServiceDarwin::lowPowerHandler (void *pvData)
     151{
     152    HostPowerServiceDarwin *pPowerObj = static_cast<HostPowerServiceDarwin *> (pvData);
     153
     154    /* Following role for sending the BatteryLow event (5% is critical):
     155     * - Not at VM start even if the battery is in an critical state already.
     156     * - When the power cord is removed so the power supply change from AC to
     157     *   battery & the battery is in an critical state nothing is triggered.
     158     *   This has to be discussed.
     159     * - When the power supply is the battery & the state of the battery level
     160     *   changed from normal to critical. The state transition from critical to
     161     *   normal triggers nothing. */
     162    bool fCriticalStateChanged = false;
     163    pPowerObj->checkBatteryCriticalLevel (&fCriticalStateChanged);
     164    if (fCriticalStateChanged)
     165        pPowerObj->notify (HostPowerEvent_BatteryLow);
     166}
     167
     168void HostPowerServiceDarwin::checkBatteryCriticalLevel (bool *pfCriticalChanged)
     169{
     170    CFTypeRef pBlob = IOPSCopyPowerSourcesInfo();
     171    CFArrayRef pSources = IOPSCopyPowerSourcesList (pBlob);
     172
     173    CFDictionaryRef pSource = NULL;
     174    const void *psValue;
     175    bool result;
     176    int powerSource = POWER_SOURCE_OUTLET;
     177    bool critical = false;
     178
     179    if (CFArrayGetCount (pSources) > 0)
     180    {
     181        for(int i = 0; i < CFArrayGetCount (pSources); ++i)
     182        {
     183            pSource = IOPSGetPowerSourceDescription (pBlob, CFArrayGetValueAtIndex (pSources, i));
     184            /* If the source is empty skip over to the next one. */
     185            if(!pSource)
     186                continue;
     187            /* Skip all power sources which are currently not present like a
     188             * second battery. */
     189            if (CFDictionaryGetValue (pSource, CFSTR (kIOPSIsPresentKey)) == kCFBooleanFalse)
     190                continue;
     191            /* Only internal power types are of interest. */
     192            result = CFDictionaryGetValueIfPresent (pSource, CFSTR (kIOPSTransportTypeKey), &psValue);
     193            if (result &&
     194                CFStringCompare ((CFStringRef)psValue, CFSTR (kIOPSInternalType), 0) == kCFCompareEqualTo)
     195            {
     196                /* First check which power source we are connect on. */
     197                result = CFDictionaryGetValueIfPresent (pSource, CFSTR (kIOPSPowerSourceStateKey), &psValue);
     198                if (result &&
     199                    CFStringCompare ((CFStringRef)psValue, CFSTR (kIOPSACPowerValue), 0) == kCFCompareEqualTo)
     200                    powerSource = POWER_SOURCE_OUTLET;
     201                else if (result &&
     202                         CFStringCompare ((CFStringRef)psValue, CFSTR (kIOPSBatteryPowerValue), 0) == kCFCompareEqualTo)
     203                    powerSource = POWER_SOURCE_BATTERY;
     204
     205                int curCapacity = 0;
     206                int maxCapacity = 1;
     207                float remCapacity = 0.0f;
     208
     209                /* Fetch the current capacity value of the power source */
     210                result = CFDictionaryGetValueIfPresent (pSource, CFSTR (kIOPSCurrentCapacityKey), &psValue);
     211                if (result)
     212                    CFNumberGetValue ((CFNumberRef)psValue, kCFNumberSInt32Type, &curCapacity);
     213                /* Fetch the maximum capacity value of the power source */
     214                result = CFDictionaryGetValueIfPresent (pSource, CFSTR (kIOPSMaxCapacityKey), &psValue);
     215                if (result)
     216                    CFNumberGetValue ((CFNumberRef)psValue, kCFNumberSInt32Type, &maxCapacity);
     217
     218                /* Calculate the remaining capacity in percent */
     219                remCapacity = ((float)curCapacity/(float)maxCapacity * 100.0);
     220
     221                /* Check for critical. 5 percent is default. */
     222                int criticalValue = 5;
     223                result = CFDictionaryGetValueIfPresent (pSource, CFSTR (kIOPSDeadWarnLevelKey), &psValue);
     224                if (result)
     225                    CFNumberGetValue ((CFNumberRef)psValue, kCFNumberSInt32Type, &criticalValue);
     226                critical = (remCapacity < criticalValue);
     227                /* We have to take action only if we are on battery, the
     228                 * previous state wasn't critical, the state has changed & the
     229                 * user requested that info. */
     230                if (powerSource == POWER_SOURCE_BATTERY &&
     231                    mCritical == false &&
     232                    mCritical != critical &&
     233                    pfCriticalChanged)
     234                    *pfCriticalChanged = true;
     235                Log (("checkBatteryCriticalLevel: Remains: %.0f%% Critical: %d Critical State Changed: %d\n", remCapacity, critical, pfCriticalChanged?*pfCriticalChanged:-1));
     236            }
     237        }
     238    }
     239    /* Save the new state */
     240    mCritical = critical;
     241
     242    CFRelease (pBlob);
     243    CFRelease (pSources);
     244}
     245
  • trunk/src/VBox/Main/include/HostPower.h

    r15454 r15905  
    9191
    9292    static DECLCALLBACK(int) powerChangeNotificationThread (RTTHREAD ThreadSelf, void *pInstance);
    93     static void powerChangeNotificationHandler (void *pData, io_service_t service, natural_t messageType, void *pMessageArgument);
    94     static OSErr lowPowerEventHandler (const AppleEvent * theAppleEvent, AppleEvent * replyAppleEvent, long refCon);
     93    static void powerChangeNotificationHandler (void *pvData, io_service_t service, natural_t messageType, void *pMessageArgument);
     94    static void lowPowerHandler (void *pvData);
     95
     96    void checkBatteryCriticalLevel (bool *pfCriticalChanged = NULL);
    9597
    9698    /* Private member vars */
     
    101103    io_object_t mNotifierObject; /* Notifier object, used to deregister later */
    102104    CFRunLoopRef mRunLoop; /* A reference to the local thread run loop */
     105
     106    bool mCritical; /* Indicate if the battery was in the critical state last checked */
    103107};
    104108# endif /* RT_OS_DARWIN */
Note: See TracChangeset for help on using the changeset viewer.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette